[NOIP2016]天天爱跑步

刚学OI 两个月上考场碰到这题表示一脸懵逼

每条路径分成两条链,一条,一条

首先考虑
不难得出,当会被观察到
观察到为定值,用桶统计即可
在点

然后是
同理可得,当会被观察到
其中的结束时间
化简得,仍然用桶统计
需要注意的是可能会有负值

还有,当时,会重复计算,记得减掉

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include<cstdio>
#include<vector>
using namespace std;
const int N=300050,rt=1;
struct node{int u,v,top;}t[N];
int n,m,w[N],cnt[N<<1],ans[N];
int dep[N],fa[N][25],log[N];
vector<int> e[N],S[N],T[N],top[N];
inline int read()
{
register int x=0,t=1;
register char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') {t=-1;ch=getchar();}
while (ch>='0'&&ch<='9') {x=x*10+ch-48;ch=getchar();}
return x*t;
}
void dfs(int o)
{
for(int i=1;i<=log[dep[o]];i++)
fa[o][i]=fa[fa[o][i-1]][i-1];
for(int i=0;i<e[o].size();i++)
{
int to=e[o][i];
if (!dep[to])
{
fa[to][0]=o;
dep[to]=dep[o]+1;
dfs(to);
}
}
}
int LCA(int u,int v)
{
if (dep[u]<dep[v]) swap(u,v);
for(int i=0;i<=log[dep[u]-dep[v]];i++)
if (((dep[u]-dep[v])>>i)&1) u=fa[u][i];
if (u==v) return u;
for(int i=log[dep[u]];i>=0;i--)
if (fa[u][i]!=fa[v][i])
u=fa[u][i],v=fa[v][i];
return fa[u][0];
}
void dfs_S(int o)
{
int pre=cnt[dep[o]+w[o]];
for(int i=0;i<e[o].size();i++)
if (dep[e[o][i]]>dep[o]) dfs_S(e[o][i]);
cnt[dep[o]]+=S[o].size();
ans[o]+=cnt[dep[o]+w[o]]-pre;
for(int i=0;i<top[o].size();i++)
cnt[dep[t[top[o][i]].u]]--;
}
void dfs_T(int o)
{
int pre=cnt[w[o]-dep[o]+N];
for(int i=0;i<e[o].size();i++)
if (dep[e[o][i]]>dep[o]) dfs_T(e[o][i]);
for(int i=0;i<T[o].size();i++)
cnt[dep[t[T[o][i]].u]-2*dep[t[T[o][i]].top]+N]++;
ans[o]+=cnt[w[o]-dep[o]+N]-pre;
for(int i=0;i<top[o].size();i++)
cnt[dep[t[top[o][i]].u]-2*dep[t[top[o][i]].top]+N]--;
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++)
log[i]=log[i-1]+(1<<log[i-1]==i);
for(int i=1;i<n;i++)
{
int u=read(),v=read();
e[u].push_back(v);
e[v].push_back(u);
}
dep[rt]=1,dfs(rt);
for(int i=1;i<=n;i++) w[i]=read();
for(int i=1;i<=m;i++)
{
t[i].u=read();
t[i].v=read();
t[i].top=LCA(t[i].u,t[i].v);
}
for(int i=1;i<=m;i++)
{
S[t[i].u].push_back(i);
T[t[i].v].push_back(i);
top[t[i].top].push_back(i);
}
dfs_S(rt),dfs_T(rt);
for(int i=1;i<=m;i++)
if (w[t[i].top]+dep[t[i].top]==dep[t[i].u]) ans[t[i].top]--;
for(int i=1;i<=n;i++) printf("%d ",ans[i]);
return 0;
}