思路是树剖求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;
}