The meaning of problems
Given a right side of a tree, the right point of v, the m given path from s to t, for each point, seeking \ (ans_i = \ Sigma_ {j = 1} ^ m [dist (s_j , i) == v [i] ] \)
Thinking
There are two possible approaches, one is the full path added to the list, and then ask each point \ (ANS \) , and the other is a one plus path, each time seeking contributions. The use of this question is the first
For each path, the \ (s-> t \) path split \ (S-> LCA-> T \) , \ (S-> LCA \) to the left of the path, \ (LCA-> T \ ) for the right path, the path to a point on the left \ (I \) , a left path if and only if it contributes \ (DEP [S] -dep [I] == V [I] \) , the \ ( I \) move the item to the side, there are \ (DEP [S] == DEP [I] + V [I] \) , so that all paths can be added to the list and then seek \ (I \) contribution point. Similarly there is a right path \ (dep [s] -2 * dep [lca] == v [i] -dep [i] \)
\ (DFS \) whole pieces tree when seeking from the back up \ (ANS \) , back to a point encountered \ (I \) , was added to it as the \ (s / t \) of the right and left paths, seek a \ (ANS \) , it is subtracted to exit \ (lca \) the path to the left and right,Then the sample had not found
(Assuming that the current in order to \ (u \) subtree is the root of the \ (the DFS \) ) because \ (u \) is a Ke subtree \ (v \) when in, \ (u \) Other inside the sub-tree path has also been recorded, then it will not lead to a path on top of it points to contribute.
Solution: Because demand is to meet the above two constraints of several paths, then enter a recursive \ (v \) before adding sub-tree inside route, subtract the first number of this time to meet the constraints of the path, thus ensuring the contribution is \ (v \) path inside the sub-tree starting
Further, if the \ (I \) is the path \ (LCA \) words may be counted twice (once for each right and left paths), so minus 1, i.e. when satisfying \ (v [lca] == dep [s] - dep [lca] \) when minus 1
Code:
#include<bits/stdc++.h>
#define N 900005
#define M 300005
using namespace std;
const int temp = 300000;
int n,m;
int dep[M],w[M],fa[M][18],ans[M];
int lsum[N],rsum[N];//桶
vector<int> L[M],R[M];//lca在上面,出
vector<int> l[M],r[M];//s,t在下面,入
struct Edge
{
int next,to;
}edge[M<<1];int head[M],cnt=1;
void add_edge(int from,int to)
{
edge[++cnt].next=head[from];
edge[cnt].to=to;
head[from]=cnt;
}
template <class T>
void read(T &x)
{
char c;int sign=1;
while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
while((c=getchar())>='0'&&c<='9') x=x*10+c-48; x*=sign;
}
void dfs(int rt)
{
dep[rt]=dep[fa[rt][0]]+1;
for(int i=head[rt];i;i=edge[i].next)
{
int v=edge[i].to;
if(v==fa[rt][0]) continue;
fa[v][0]=rt;
for(int i=1;i<18;++i) fa[v][i]=fa[fa[v][i-1]][i-1];
dfs(v);
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
for(int i=17;i>=0;--i) if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];
if(x==y) return x;
for(int i=17;i>=0;--i) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
void DFS(int rt)
{
ans[rt]-=lsum[dep[rt]+w[rt]+temp]+rsum[w[rt]-dep[rt]+temp];
for(int i=head[rt];i;i=edge[i].next)
{
int v=edge[i].to;
if(v==fa[rt][0]) continue;
DFS(v);
}
//加入rt
for(int i=0;i<(int)l[rt].size();++i)
{
int val=l[rt][i]+temp;
++lsum[val];
}
for(int i=0;i<(int)r[rt].size();++i)
{
int val=r[rt][i]+temp;
++rsum[val];
}
ans[rt]+=lsum[dep[rt]+w[rt]+temp]+rsum[w[rt]-dep[rt]+temp];
//删除以rt为lca的链
for(int i=0;i<(int)L[rt].size();++i)
{
int val=L[rt][i]+temp;
--lsum[val];
}
for(int i=0;i<(int)R[rt].size();++i)
{
int val=R[rt][i]+temp;
--rsum[val];
}
}
int main()
{
read(n);read(m);
for(int i=1;i<n;++i)
{
int x,y;
read(x);read(y);
add_edge(x,y);
add_edge(y,x);
}
dfs(1);
for(int i=1;i<=n;++i) read(w[i]);
for(int i=1;i<=m;++i)
{
int S,T;
read(S);read(T);
int lc=lca(S,T);
if(w[lc]==dep[S]-dep[lc]) ans[lc]--;
L[lc].push_back(dep[S]);
R[lc].push_back(dep[S]-2*dep[lc]);
l[S].push_back(dep[S]);
r[T].push_back(dep[S]-2*dep[lc]);
}
DFS(1);
for(int i=1;i<=n;++i) printf("%d ",ans[i]);
return 0;
}