ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

亿些原古博客汇总 II

2022-02-07 19:00:08  阅读:145  来源: 互联网

标签:ch 亿些 int long II read 原古 dp getchar


之前那个太满了编辑一下卡一年所以就新开一个。

[USACO12FEB]Nearby Cows G [2]

一句话题意:给你一棵 \(n\) 个点的树,点带权,对于每个节点求出距离它不超过 \(k\) 的所有节点权值和 \(m_i\) 。

\(1 \le n \le 10^5\)

定睛一看这就是今年省选B卷D1T2的60pts数据嘛。

k的范围很小,可以用\(O(nk)\)的算法水过去。其实就是换根dp

令\(dp[u][k]\)代表u到其子树内距离为k的点的权值和,有\(dp[u][k]+=dp[v][k-1]\)。

然后考虑怎么从父亲扩展到儿子,其实就是一步容斥:\(f[v][k]=dp[v][k]+f[u][k-1]-dp[v][k-2]\)。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
typedef long long ll;
const int N = 100010;
const int K = 22;
const int inf = 0x3f3f3f3f;
template <typename T> void read(T &x) {
	T w = 1;
	char ch = getchar();
	for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1;
	for (x = 0; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
	x *= w;
}
struct node{
	int pre, to;
}edge[N << 1];
int head[N], tot;
int n, k;
int dp[N][K], f[N][K];
void add(int u, int v) {
	edge[++tot] = node{head[u], v};
	head[u] = tot;
}
void dfs1(int x, int fa) {
	for (int i = head[x]; i; i = edge[i].pre) {
		int y = edge[i].to;
		if (y == fa) continue;
		dfs1(y, x);
		for (int j = 1; j <= k; j++) {
			dp[x][j] += dp[y][j - 1];
		}
	}
}
void dfs2(int x, int fa) {
	f[x][0] = dp[x][0];
	for (int i = head[x]; i; i = edge[i].pre) {
		int y = edge[i].to;
		if (y == fa) continue;
		for (int j = 1; j <= k; j++) {
			if (j > 1) f[y][j] = dp[y][j] + (f[x][j - 1] - dp[y][j - 2]);
			else f[y][j] = dp[y][j] + (f[x][j - 1]);
		}
		dfs2(y, x);
	}
}
int main() {
	read(n); read(k);
	for (int i = 1, u, v; i < n; i++) {
		read(u); read(v);
		add(u, v);
		add(v, u);
	}
	for (int i = 1; i <= n; i++) read(dp[i][0]);
	dfs1(1, 0);
	for (int i = 1; i <= k; i++) f[1][i] = dp[1][i];
	dfs2(1, 0);
	for (int i = 1; i <= n; i++) {
		for (int j = 0; j <= k; j++) {
			f[i][j] += f[i][j - 1];
		}
		printf("%d\n", f[i][k]);
	}
	return 0;
}

[USACO10MAR]Great Cow Gathering G [2]

换根dp模板题。

同时记录\(sz[u]\)代表\(u\)的子树内有多少奶牛,那转移时即为\(dp[u]=dp[v]+sz[v] \times val(u,v)\)。

注意开long long。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100010;
const ll inf = 0x7f7f7f7f7f7f7f7f;
template <typename T> void read(T &x) {
	T f = 1;
	char ch = getchar();
	for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
	for (x = 0; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
	x *= f;
}
template <typename T> void cmin(T &x, T y) {if (y < x) x = y;}
struct node{
	int pre, to;
	ll val;
}edge[N << 1];
int head[N], tot;
int n;
int c[N];
ll dp[N], sz[N];
ll ans = inf;
void add(int u, int v, int l) {
	edge[++tot] = node{head[u], v, l};
	head[u] = tot;
}
void dfs1(int x, int fa) {
	sz[x] = c[x];
	for (int i = head[x]; i; i = edge[i].pre) {
		int y = edge[i].to;
		if (y == fa) continue;
		dfs1(y, x);
		sz[x] += sz[y];
		dp[x] += dp[y] + sz[y] * edge[i].val;
	}
}
void cut(int x, int y, int val) {
	dp[x] -= dp[y] + sz[y] * val;
	sz[x] -= sz[y];
}
void link(int x, int y, int val) {
	dp[x] += dp[y] + sz[y] * val;
	sz[x] += sz[y];
}
void change_root(int x, int y, int val) {
	cut(x, y, val);
	link(y, x, val);
}
void dfs2(int x, int fa) {
	cmin(ans, dp[x]);
	for (int i = head[x]; i; i = edge[i].pre) {
		int y = edge[i].to;
		if (y == fa) continue;
		change_root(x, y, edge[i].val);
		dfs2(y, x);
		change_root(y, x, edge[i].val);
	}
}
int main() {
	read(n);
	for (int i = 1; i <= n; i++) read(c[i]);
	for (int i = 1, a, b, v; i < n; i++) {
		read(a); read(b); read(v);
		add(a, b, v);
		add(b, a, v);
	}
	dfs1(1, 0);
	dfs2(1, 0);
	printf("%lld", ans);
	return 0;
}

标签:ch,亿些,int,long,II,read,原古,dp,getchar
来源: https://www.cnblogs.com/zcr-blog/p/15868871.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有