True · NOIp day1 T2
As we all know noip by the difficulty of the topic and order
Thank Luo Gu solution to a problem @ greenlcat provide ideas and writing
+ + Write tune written explanations total of 2.5 hours for a whole night to night classes today, I got nothing dry
Step by step to solve this problem
Step 1: multiplying LCA
This problem itself is not a small amount of code, also written tree section LCA, my chicken dish not out of tune
Doubling seeking LCA seems nothing to write basic operation
1 int n,m,cnt,deep[maxn],fa[maxn][25],w[maxn],head[maxn]; 2 struct edge{ 3 int nxt,to; 4 }e[maxn*2]; 5 inline void add(int from,int to){ 6 e[++cnt].to=to;e[cnt].nxt=head[from];head[from]=cnt; 7 } 8 void dfs1(int x){ 9 for(int i=1;(1<<i)<=deep[x];i++){ 10 fa[x][i]=fa[fa[x][i-1]][i-1]; 11 } 12 for(int i=head[x];i;i=e[i].nxt){ 13 int y=e[i].to; 14 if(y==fa[x][0])continue; 15 fa[y][0]=x; 16 deep[y]=deep[x]+1; 17 dfs1(y); 18 } 19 } 20 int lca(int x,int y){ 21 if(x==y)return x; 22 if(deep[x]<deep[y])swap(x,y); 23 int k=log(deep[x]-deep[y])/log(2); 24 for(int i=k;i>=0;i--){ 25 if(deep[fa[x][i]]>=deep[y]){ 26 x=fa[x][i]; 27 } 28 if(x==y)return x; 29 } 30 k=log(deep[x])/log(2); 31 for(int i=k;i>=0;i--){ 32 if(fa[x][i]!=fa[y][i]){ 33 x=fa[x][i];y=fa[y][i]; 34 } 35 } 36 return fa[x][0]; 37 } 38 int main(){ 39 n=read();m=read(); 40 for(int i=1;i<n;i++){ 41 int u,v;u=read();v=read(); 42 add(u,v);add(v,u); 43 } 44 deep[1]=1;fa[1][0]=1;dfs1(1); 45 for(int i=1;i<=n;i++){ 46 w[i]=read(); 47 } 48 return 0; 49 }
Step 2: Analyze conversion
Found that simulate the complexity of each player's explosion, divide it is impossible to consider the overall process
To enumerate each observer, observer contribute to see which nodes (which may be observed)
The observer may be converted into the enumeration dfs entire tree, O (n) may be acceptable
Consider an observer for x, if he was on a $ s_i $ to $ t_i $ path
1. If x is on the $ LCA $ S_I
When S_I $ $ satisfy $ deep [{s_i}] = w [x] + deep [x] $, $ s_i $ x has a contribution of 1
2. If x in $ $ t_i to LCA
When t_i $ $ satisfy $ dis [{s_i}, {t_i}] - deep [{t_i}] = w [x] -deep [x] $ time, $ t_i $ x has a contribution of 1
So we found capable of contributing $ s_i $ x or $ t_i $ are to the sub-tree rooted at x
Step 3: stats Contribution
code (comments in the code)
1 struct edge{ 2 int nxt,to; 3 }e1[maxn*2],e2[maxn*2]; 4 inline void add1(int from,int to){ 5 e1[++cnt1].to=to;e1[cnt1].nxt=h1[from];h1[from]=cnt1; 6 } 7 inline void add2(int from,int to){ 8 e2[++cnt2].to=to;e2[cnt2].nxt=h2[from];h2[from]=cnt2; . 9 } 10 int B1 [MAXN * 2 ], B2 [MAXN * 2 ], JS [MAXN], DIS [MAXN]; . 11 int S [MAXN], L [MAXN], T [MAXN], ANS [MAXN]; 12 is void DFS2 ( int X) { 13 is int T1 = B1 [W [X] Deep + [X]], T2 = B2 [W [X] -deep [X] + MAXN]; 14 // front barrel recursive prefetch in value, t1 is a value up bucket, t2 is a value downlink bucket 15 for ( int I = head [X]; I; I = E [I] .nxt) { // recursive subtree 16 int Y = E [I] .to; . 17 IF (FA == Y [X] [ 0 ]) Continue ; 18 is DFS2 (Y); . 19 } 20 is B1 [Deep [X]] = + JS [X]; 21 is // up process, the current path as the starting point produce contribution, into the tub 22 is for ( int I = h1 of [X]; I; I = [I] .nxt) {E1 23 is // downlink process, the current point as the end of the path generation contribution, into the tub 24 int Y = E1 [I] .to; 25 B2 [DIS [Y] -deep [ T [Y]] + MAXN] ++ ; 26 is } 27 ANS [X] + = B1 [W [X] Deep + [X]] - T1 + B2 [W [X] -deep [X] + MAXN] - T2; 28 // computationally downlink barrel difference to accumulated ans [x] inside 29 for ( int I = H2 [X]; I; I = E2 [I] .nxt) { 30 // before backtracking remove this contribution LCA node start and end in the barrel produced, they have a void 31 is int Y = E2 [I] .to; 32 B1 [Deep [S [Y]]] - ; 33 is B2 [DIS [Y] -deep [T [Y]] + MAXN] - ; 34 is } 35 } 36 int main () { 37 [ for ( int I = . 1 ; I <= m; I ++ ) { 38 is S [I] = Read (); T [I] = Read (); 39 int LCAA LCA = (S [I], T [I]); // find the LCA 40 DIS [I] = Deep [S [I] ] + Deep [T [I]] - 2 * Deep [LCAA]; 41 is JS [s [i]] ++; // statistics to s [i] is the number of paths starting bar 42 is ADD1 (t [i], i); // i th path is added to to t [i] as the end point the set of paths 43 is ADD2 (LCAA, I); // the return path of each set corresponding to the LCA 44 is IF (Deep [LCAA] + W [LCAA] == Deep [S [I]]) { 45 / / If the path just as the start or end of the LCA and LCA is observable athletes answer - 46 is ANS [LCAA] - ; 47 } 48 } 49 DFS2 ( . 1 ); 50 for ( int I = . 1 ; I < n-=; I ++ ) { 51 is the printf ( " % LLD",ans[i]); 52 } 53 return 0; 54 }
Full HD without comment code
1 #include <bits/stdc++.h> 2 using namespace std; 3 namespace gengyf{ 4 #define ll long long 5 #define int long long 6 const int maxn=3e5+10; 7 inline int read(){ 8 int x=0,f=1; 9 char c=getchar(); 10 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 11 while(c>='0'&&c<='9'){x=(x*10)+c-'0';c=getchar();} 12 return x*f; 13 } 14 int n,m,cnt,deep[maxn],fa[maxn][25],w[maxn],head[maxn]; 15 int h1[maxn],h2[maxn],cnt1,cnt2; 16 struct edge{ 17 int nxt,to; 18 }e[maxn*2],e1[maxn*2],e2[maxn*2]; 19 inline void add(int from,int to){ 20 e[++cnt].to=to;e[cnt].nxt=head[from];head[from]=cnt; 21 } 22 inline void add1(int from,int to){ 23 e1[++cnt1].to=to;e1[cnt1].nxt=h1[from];h1[from]=cnt1; 24 } 25 inline void add2(int from,int to){ 26 e2[++cnt2].to=to;e2[cnt2].nxt=h2[from];h2[from]=cnt2; 27 } 28 void dfs1(int x){ 29 for(int i=1;(1<<i)<=deep[x];i++){ 30 fa[x][i]=fa[fa[x][i-1]][i-1]; 31 } 32 for(int i=head[x];i;i=e[i].nxt){ 33 int y=e[i].to; 34 if(y==fa[x][0])continue; 35 fa[y][0]=x; 36 deep[y]=deep[x]+1; 37 dfs1(y); 38 } 39 } 40 int lca(int x,int y){ 41 if(x==y)return x; 42 if(deep[x]<deep[y])swap(x,y); 43 int k=log(deep[x]-deep[y])/log(2); 44 for(int i=k;i>=0;i--){ 45 if(deep[fa[x][i]]>=deep[y]){ 46 x=fa[x][i]; 47 } 48 if(x==y)return x; 49 } 50 k=log(deep[x])/log(2); 51 for(int i=k;i>=0;i--){ 52 if(fa[x][i]!=fa[y][i]){ 53 x=fa[x][i];y=fa[y][i]; 54 } 55 } 56 return fa[x][0]; 57 } 58 int b1[maxn*2],b2[maxn*2],js[maxn],dis[maxn]; 59 int s[maxn],l[maxn],t[maxn],ans[maxn]; 60 void dfs2(int x){ 61 int t1=b1[w[x]+deep[x]],t2=b2[w[x]-deep[x]+maxn]; 62 for(int i=head[x];i;i=e[i].nxt){ 63 int y=e[i].to; 64 if(y==fa[x][0])continue; 65 dfs2(y); 66 } 67 b1[deep[x]]+=js[x]; 68 for(int i=h1[x];i;i=e1[i].nxt){ 69 int y=e1[i].to; 70 b2[dis[y]-deep[t[y]]+maxn]++; 71 } 72 ans[x]+=b1[w[x]+deep[x]]-t1+b2[w[x]-deep[x]+maxn]-t2; 73 for(int i=h2[x];i;i=e2[i].nxt){ 74 int y=e2[i].to; 75 b1[deep[s[y]]]--; 76 b2[dis[y]-deep[t[y]]+maxn]--; 77 } 78 } 79 int main(){ 80 n=read();m=read(); 81 for(int i=1;i<n;i++){ 82 int u,v;u=read();v=read(); 83 add(u,v);add(v,u); 84 } 85 deep[1]=1;fa[1][0]=1;dfs1(1); 86 for(int i=1;i<=n;i++){ 87 w[i]=read(); 88 } 89 for(int i=1;i<=m;i++){ 90 s[i]=read();t[i]=read(); 91 int lcaa=lca(s[i],t[i]); 92 dis[i]=deep[s[i]]+deep[t[i]]-2*deep[lcaa]; 93 js[s[i]]++; 94 add1(t[i],i);add2(lcaa,i); 95 if(deep[lcaa]+w[lcaa]==deep[s[i]]){ 96 ans[lcaa]--; 97 } 98 } 99 dfs2(1); 100 for(int i=1;i<=n;i++){ 101 printf("%lld ",ans[i]); 102 } 103 return 0; 104 } 105 } 106 signed main(){ 107 gengyf::main(); 108 return 0; 109 }
End sprinkle flower