我们把每一条路径拆成$u->lca$和$lca->v$的路径
先考虑$u->lca$,如果这条路径会对路径上的某一个点产生贡献,那么满足$dep[u]-dep[x]=w[x],dep[u]=dep[x]+w[x]$,注意到$dep[x]+w[x]$是一个定值,所以我们只要去找它的子树里有多少个点的$dep$等于$dep[x]+w[x]$就可以了,这个可以直接开一个桶。然而如果点$x$在$lca$的上面,这一条路径是不会对他产生贡献的,那么我们就得在$lca$处把这一条路径的贡献给减去。具体怎么做呢?我们可以利用树上差分的思想,在点$u$把它的出现次数$+1$,在$lca$处把它的出现次数$-1$,那么我们对于每一个点,只要去查询它的子树里$dep[x]+w[x]$这个值出现了多少次就可以了。
顺便注意一下,因为我们的桶里存的不止是一棵子树的答案,所以查询得到的次数可能是来子其他子树的。那么我们可以dfs进去之前先记录一下,完了之后再记录一下,两次的差就是这个值在其子树里的实际出现次数
然后$lca->v$的路径咋搞嘞?只要把式子改成$dep[v]-dep[x]=len-w[i]$($len$表示路径长度),然后和上面一样的做法。注意这里有可能会出现负数,所以我们要让它加上$3e5$
注意到$lca$会被我们统计两次,那么我们只要最后做完之后,把所有被统计了两次答案的$lca$答案减一就好了
1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 8 char buf[1<<21],*p1=buf,*p2=buf; 9 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} 10 inline int read(){ 11 #define num ch-'0' 12 char ch;bool flag=0;int res; 13 while(!isdigit(ch=getc())) 14 (ch=='-')&&(flag=true); 15 for(res=num;isdigit(ch=getc());res=res*10+num); 16 (flag)&&(res=-res); 17 #undef num 18 return res; 19 } 20 char sr[1<<21],z[20];int C=-1,Z; 21 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;} 22 inline void print(int x){ 23 if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x; 24 while(z[++Z]=x%10+48,x/=10); 25 while(sr[++C]=z[Z],--Z);sr[++C]=' '; 26 } 27 const int N=300005,M=600005; 28 int head[N],Next[M],ver[M],tot; 29 int son[N],sz[N],fa[N],dep[N],top[N]; 30 int c[N],w[N],val[N],num[1000005]; 31 int n,m,lim,ans[N]; 32 vector<int> qaq[N],qaq2[N],qaq3[N]; 33 struct node{int s,t,lca,len;}q[N]; 34 inline void add(int u,int v){ 35 ver[++tot]=v,Next[tot]=head[u],head[u]=tot; 36 ver[++tot]=u,Next[tot]=head[v],head[v]=tot; 37 } 38 void dfs1(int u){ 39 sz[u]=1,dep[u]=dep[fa[u]]+1,cmax(lim,dep[u]); 40 for(int i=head[u];i;i=Next[i]){ 41 int v=ver[i]; 42 if(v!=fa[u]){ 43 fa[v]=u,dfs1(v),sz[u]+=sz[v]; 44 if(sz[v]>sz[son[u]]) son[u]=v; 45 } 46 } 47 } 48 void dfs2(int u,int t){ 49 top[u]=t; 50 if(son[u]) dfs2(son[u],t);else return; 51 for(int i=head[u];i;i=Next[i]){ 52 int v=ver[i]; 53 if(v!=fa[u]&&v!=son[u]) dfs2(v,v); 54 } 55 } 56 inline int LCA(int u,int v){ 57 while(top[u]!=top[v]){ 58 if(dep[top[u]]<dep[top[v]]) swap(u,v);u=fa[top[u]]; 59 } 60 return dep[u]<dep[v]?u:v; 61 } 62 void dfs(int u,int fa){ 63 int now=w[u]+dep[u],k;if(now<=lim) k=c[now]; 64 for(int i=head[u];i;i=Next[i]){ 65 int v=ver[i];if(v!=fa) dfs(v,u); 66 } 67 c[dep[u]]+=val[u];if(now<=lim) ans[u]=c[now]-k; 68 for(int i=0,s=qaq[u].size();i<s;++i) --c[dep[qaq[u][i]]]; 69 } 70 void DFS(int u,int fa){ 71 int now=dep[u]-w[u],k;now+=300000,k=num[now]; 72 for(int i=head[u];i;i=Next[i]){ 73 int v=ver[i];if(v!=fa) DFS(v,u); 74 } 75 for(int i=0,s=qaq2[u].size();i<s;++i) ++num[300000+qaq2[u][i]]; 76 ans[u]+=num[now]-k; 77 for(int i=0,s=qaq3[u].size();i<s;++i) --num[300000+qaq3[u][i]]; 78 } 79 int main(){ 80 //freopen("testdata.in","r",stdin); 81 n=read(),m=read(); 82 for(int i=1;i<n;++i){ 83 int u=read(),v=read();add(u,v); 84 } 85 for(int i=1;i<=n;++i) w[i]=read(); 86 dfs1(1),dfs2(1,1); 87 for(int i=1;i<=m;++i){ 88 q[i].s=read(),q[i].t=read(),++val[q[i].s]; 89 q[i].lca=LCA(q[i].s,q[i].t),q[i].len=dep[q[i].s]+dep[q[i].t]-dep[q[i].lca]*2; 90 qaq[q[i].lca].push_back(q[i].s); 91 } 92 dfs(1,0); 93 for(int i=1;i<=m;++i){ 94 qaq2[q[i].t].push_back(dep[q[i].t]-q[i].len); 95 qaq3[q[i].lca].push_back(dep[q[i].t]-q[i].len); 96 } 97 DFS(1,0); 98 for(int i=1;i<=m;++i) if(dep[q[i].s]-dep[q[i].lca]==w[q[i].lca]) --ans[q[i].lca]; 99 for(int i=1;i<=n;++i) print(ans[i]); 100 Ot(); 101 return 0; 102 }