题目大意:给你一颗树,树上每个点都有一个观察员,他们仅会在 w[i] 时刻出现,观察正在跑步的玩家
一共有m个玩家,他们分别从节点 s[i] 同时出发,以每秒跑一条边的速度,沿着到 t[i] 的唯一路径向节点t[i]奔跑
如果一名玩家已经到达了终点,那么在他到达终点之后出现在终点的观察员不会观察到他
但如果在到达终点的同时观察员也出现在终点,那么观察员可以观察到他
求每个节点的观察员观察到玩家的数量
对于每个玩家的奔跑路线,可以拆成两部分
<1>向上跑,从 u 向 lca 奔跑
显然,玩家 u 能对观察员 i 产生1点贡献的充要条件为
显然,向上走的路线能对 i 点产生共贡献的条件是,起点 u 在 i 的子树中
我们只需要统计符合条件的即可
<2>向下跑,从 lca 向 v 奔跑
那么显然
推导可得
显然,向下走的路线能对i点产生共贡献的条件是,终点 v 在 i 的子树中
类似于上面的方法,我们只需要统计符合条件的即可
我们可以用vector在u,v,lca这三个点上打差分,存符合条件的值,注意值可能为负数
而其他子树的结果会影响答案,所以深搜统计一次答案,再用回溯的答案减去深搜的答案即可
方法比较奇葩大家凑合看吧。。。
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <vector> 5 #define N 300010 6 #define maxn 300000 7 using namespace std; 8 9 int n,m,cte; 10 int dep[N],fa[N],tp[N],sz[N],son[N],ans[N]; 11 int w[N],s[N],t[N],F[N],bac[N*3],head[N],tmp[N]; 12 struct EDGE{ 13 int to,nxt; 14 }edge[N*2]; 15 vector<int>S[N]; 16 vector<int>E[N]; 17 int gc() 18 { 19 int rett=0,fh=1;char p=getchar(); 20 while(p<'0'||p>'9') {if(p=='-')fh=-1;p=getchar();} 21 while(p>='0'&&p<='9') {rett=rett*10+p-'0';p=getchar();} 22 return rett*fh; 23 } 24 void edge_add(int u,int v) 25 { 26 cte++; 27 edge[cte].to = v; 28 edge[cte].nxt=head[u]; 29 head[u]=cte; 30 } 31 void Tsp1(int u,int dad) 32 { 33 for(int j=head[u];j!=-1;j=edge[j].nxt) 34 { 35 int v=edge[j].to; 36 if(v==dad) continue; 37 dep[v]=dep[u]+1; 38 fa[v]=u; 39 Tsp1(v,u); 40 if(sz[v]>sz[son[u]]) son[u]=v; 41 sz[u]+=sz[v]; 42 } 43 sz[u]++; 44 } 45 void Tsp2(int u) 46 { 47 if(son[u]) tp[son[u]]=tp[u],Tsp2(son[u]); 48 for(int j=head[u];j!=-1;j=edge[j].nxt) 49 { 50 int v=edge[j].to; 51 if(v==fa[u]||v==son[u]) continue; 52 tp[v]=v; 53 Tsp2(v); 54 } 55 } 56 int LCA(int x,int y) 57 { 58 while(tp[x]!=tp[y]) 59 { 60 if(dep[tp[x]]<dep[tp[y]]) swap(x,y); 61 x=fa[tp[x]]; 62 } 63 return dep[x]<=dep[y]?x:y; 64 } 65 void dfs1(int u) 66 { 67 tmp[u]=bac[dep[u]+w[u]+maxn]; 68 for(int j=head[u];j!=-1;j=edge[j].nxt) 69 { 70 int v=edge[j].to; 71 if(v==fa[u]) continue; 72 dfs1(v); 73 } 74 for(int i=0;i<S[u].size();i++) 75 bac[S[u][i]+maxn]++; 76 ans[u]+=bac[dep[u]+w[u]+maxn]-tmp[u]; 77 for(int i=0;i<E[u].size();i++) 78 bac[E[u][i]+maxn]--; 79 } 80 void dfs2(int u) 81 { 82 tmp[u]=bac[w[u]-dep[u]+maxn]; 83 for(int j=head[u];j!=-1;j=edge[j].nxt) 84 { 85 int v=edge[j].to; 86 if(v==fa[u]) continue; 87 dfs2(v); 88 } 89 for(int i=0;i<E[u].size();i++) 90 bac[E[u][i]+maxn]--; 91 for(int i=0;i<S[u].size();i++) 92 bac[S[u][i]+maxn]++; 93 ans[u]+=bac[w[u]-dep[u]+maxn]-tmp[u]; 94 } 95 96 int main() 97 { 98 freopen("running1.in","r",stdin); 99 //freopen("running6.out","w",stdout); 100 scanf("%d%d",&n,&m); 101 int x,y; 102 memset(head,-1,sizeof(head)); 103 for(int i=1;i<n;i++) 104 { 105 x=gc(),y=gc(); 106 edge_add(x,y); 107 edge_add(y,x); 108 } 109 tp[1]=1; 110 Tsp1(1,-1); 111 Tsp2(1); 112 for(int i=1;i<=n;i++) w[i]=gc(); 113 for(int i=1;i<=m;i++) 114 { 115 s[i]=gc(),t[i]=gc(); 116 F[i]=LCA(s[i],t[i]); 117 S[s[i]].push_back(dep[s[i]]); 118 E[F[i]].push_back(dep[s[i]]); 119 } 120 //debug(); 121 dfs1(1); 122 for(int i=1;i<=n;i++) 123 { 124 S[i].clear(),E[i].clear(); 125 } 126 memset(tmp,0,sizeof(tmp)); 127 for(int i=1;i<=m;i++) 128 { 129 S[t[i]].push_back(dep[s[i]]-2*dep[F[i]]); 130 E[F[i]].push_back(dep[s[i]]-2*dep[F[i]]); 131 } 132 dfs2(1); 133 for(int i=1;i<=n;i++) printf("%d ",ans[i]); 134 return 0; 135 }