2020 CCPC-Wannfaly-da1 树与路径

回想Day1真是可怕,场场都是倒数的。。。。(金牌爷太强了)

题目如下(吉老师出的题)

传送门:https://ac.nowcoder.com/acm/contest/3979/E

 个人感觉这题不是很难那种(不过比赛时候确实没写出来)因为确实没有练习过树上差分,不知道树上前缀和有什么用。。。

 公式就是这样了,吉老师写的更简便,(但是看不懂)

#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn = 3e5 + 100;
ll dep[maxn];
int f[maxn][30];
ll dp[maxn];//答案
ll list[maxn];//前缀
ll cnt[maxn];
ll ans[maxn];

vector<int>G[maxn];
void insert(int be, int en) {
	G[be].push_back(en);
}

int dfs(int x, int fa) {
	dep[x] = dep[fa] + 1;
	for (int i = 0; i < G[x].size(); i++) {
		int p = G[x][i];
		if (p == fa) continue;
		f[p][0] = x;
		dfs(p, x);
	}
	return 0;
}
int LCA(int x, int y) {
	if (dep[x] > dep[y]) swap(x, y);
	for (int i = 22; i >= 0; i--) {
		if (dep[x] <= dep[f[y][i]]) {
			y = f[y][i];
		}
	}
	if (x == y) return x;
	for (int i = 22; i >= 0; i--) {
		if (f[x][i] != f[y][i]) {
			x = f[x][i];
			y = f[y][i];
		}
	}
	return f[x][0];
}
struct node {
	int be, en;
	ll len;
}que[maxn];
int dfs1(int x, int fa) {
	for (int i = 0; i < G[x].size(); i++) {
		int p = G[x][i];
		if (p == fa) continue;
		dfs1(p, x);
		ans[x] += ans[p];
		cnt[x] += cnt[p];
	}
	list[x] = cnt[x];
	return 0;
}

int dfs2(int x, int fa) {

	for (int i = 0; i < G[x].size(); i++) {
		int p = G[x][i];
		if (p == fa) continue;
		dfs2(p, x);
		ans[x] += ans[p];
		list[x] += list[p];
	}
	return 0;
}

int dfs3(int x, int fa) {

	for (int i = 0; i < G[x].size(); i++) {
		int p = G[x][i];
		if (p == fa) continue;
		dp[p] = dp[x] + 2 * list[p] - ans[p] - cnt[p];
		dfs3(p, x);
	}
	return 0;
}
int main() {
	int n, m;
	int be, en;
	scanf("%d %d", &n, &m);
	for (int i = 1; i < n; i++) {
		scanf("%d %d", &be, &en);
		insert(be, en);
		insert(en, be);
	}
	dfs(1, 0);
	for (int k = 1; k < 25; k++) {
		for (int i = 1; i <= n; i++) {
			f[i][k] = f[f[i][k - 1]][k - 1];
		}
	}
	ll cns = 0;
	for (int i = 0; i < m; i++) {
		scanf("%d %d", &be, &en);
		int root = LCA(be, en);
		cnt[be]++;
		cnt[en]++;
		cnt[root] -= 2;
		ll d = dep[be] + dep[en] - 2 * dep[root];
		que[i].be = be;
		que[i].en = en;
		que[i].len = d;
		dp[1] += 1LL*(dep[be] - dep[root])*(dep[en] - dep[root]);
	}
	dfs1(1, -1);
	ll len;
	for (int i = 0; i < m; i++) {
		be = que[i].be;
		en = que[i].en;
		len = que[i].len;
		int root = LCA(be, en);
		ans[be] += len;
		ans[en] += len;
		ans[root] -= 2 * len;
		
		list[root] -= (dep[be] - dep[root]);
		list[root] -= (dep[en] - dep[root]);

	}
	dfs2(1, -1);
	dfs3(1, -1);
	for (int i = 1; i <= n; i++) {
		printf("%lld
", dp[i]);
	}
	return 0;
}

  

寻找真正的热爱
原文地址:https://www.cnblogs.com/lesning/p/12217984.html