25pts求助
查看原帖
25pts求助
756660
B612Dusk楼主2023/11/6 18:25

思路是树剖求lca+树上差分,用的是类似于雨天的尾巴那道题的思路,分开向上走和向下走的两次处理,lca重复的处理方法是在向下走的时候求下一级祖先,错开打标记,但是只过了 起点=终点 和 一条链 的情况,样例和自己手开了 12 组都过了,求助。

#include <cstdio>
#include <map>
#include <vector>

#define N 1000100
using namespace std;

inline int read()
{
	int x = 0, f = 1;  char ch = getchar();
	while(ch > '9' || ch < '0'){
		if(ch == '-') f = -1;
		ch = getchar();
	}
	while(ch >= '0' && ch <= '9'){
		x = (x << 3) + (x << 1) + (ch ^ 48);
		ch = getchar();
	}
	return x * f;
}

int n, m;
int t[N];

inline void swap(int &x, int &y)
{
	x ^= y ^= x ^= y;
}

struct edges{
	int nxt, ver;
}edge[N << 1];

int head[N], tot;
inline void add(int a, int b)
{
	edge[++ tot] = {head[a], b};
	head[a] = tot;
}

int fa[N], sze[N], son[N], dep[N];
void get_son(int x, int Fa)
{
	fa[x] = Fa;
	sze[x] = 1;
	dep[x] = dep[Fa] + 1;
	for(int i = head[x]; i; i = edge[i].nxt)
	{
		int y = edge[i].ver;
		if(y == Fa)	 continue;
		get_son(y, x);
		sze[x] += sze[y];
		sze[son[x]] < sze[y] ? son[x] = y : y = y;
	}
}

int top[N], dfn[N], idx, nfd[N];
void get_chain(int x, int Top)
{
	top[x] = Top;
	dfn[x] = ++ idx;
	nfd[idx] = x;
	if(!son[x])	 return;
	get_chain(son[x], Top);
	for(int i = head[x]; i; i = edge[i].nxt)
	{
		int y = edge[i].ver;
		if(y == son[x] || y == fa[x])	continue;
		get_chain(y, y);
	}
}

int Lca(int x, int y)
{
	while(top[x] != top[y])
	{
		if(dep[top[x]] < dep[top[y]])	swap(x, y);
		x = fa[top[x]];
	}
	if(dep[x] > dep[y])	return y;
	else	return x;
}

map<int, int> cnt;
int ans[N];

vector<int> ins[N], del[N]; 
vector<int> Ins[N], Del[N]; 

void dfs_up(int x, int Fa) 
{
	bool leaf = 1;
	for(int i = head[x]; i; i = edge[i].nxt)
	{
		int y = edge[i].ver;
		if(y == Fa)	 continue;
		dfs_up(y, x);
	}
	for(int j = 0;j < ins[x].size();j = -~j)	++ cnt[ins[x][j]];
	ans[x] += cnt[t[x] + dep[x]];
	for(int j = 0;j < del[x].size();j = -~j)	-- cnt[del[x][j]]; 
}

void dfs_down(int x, int Fa)
{
	bool leaf = 1;
	for(int i = head[x]; i ; i = edge[i].nxt)
	{
		int y = edge[i].ver;
		if(y == Fa)	 continue;
		dfs_down(y, x);
		leaf = 0;
	}
	for(int j = 0;j < Ins[x].size();j = -~j)	++ cnt[Ins[x][j]];
	ans[x] += cnt[t[x] - dep[x]];
	for(int j = 0;j < Del[x].size();j = -~j) 	-- cnt[Del[x][j]];
}

inline int jmp(int x, int y) 
{
	while(top[x] != top[y]) 
	{
		if(fa[top[y]] == x) return top[y];
		y = fa[top[y]]; 
	}
	return nfd[dfn[x] + 1];
}

signed main()
{
//	freopen(".in","r",stdin);
	n = read(), m = read();
	for(int i = 1;i < n;i = -~i)
	{
		int a = read(), b = read();
		add(a, b), add(b, a);
	}
	
	for(int i = 1;i <= n;i = -~i)	t[i] = read();
	
	get_son(1, 0);
	get_chain(1, 1);
	
	while(m --)
	{
		int x = read(), y = read(); 
		int lca = Lca(x, y);
		
		if(lca == x)
		{
			int Dis = dep[x] + dep[y] - (dep[lca] << 1); 
			Ins[y].emplace_back(Dis - dep[y]); 
			Del[lca].emplace_back(Dis - dep[y]); 
		}
		
		else if(lca == y)
		{
			ins[x].emplace_back(dep[x]); 
			del[lca].emplace_back(dep[x]);
		}
		
		else
		{
			ins[x].emplace_back(dep[x]);
			del[lca].emplace_back(dep[x]);
			
			int Dis = dep[x] + dep[y] - (dep[lca] << 1); 
			int jp = jmp(lca, y);
			Ins[y].emplace_back(Dis - dep[y]); 
			Del[jp].emplace_back(Dis - dep[y]); 
		}
		
	}
	
	dfs_up(1, 1); 
	cnt.clear(); 
	dfs_down(1, 1); 
	
	for(int i = 1;i <= n;i = -~i)	printf("%d ", ans[i]); 
	return 0; 
}
2023/11/6 18:25
加载中...