[Explanations] Luogu P1600 LCA + trees difference

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 }
part one

 

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 }
part two

 

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 }
View Code

 

End sprinkle flower

Guess you like

Origin www.cnblogs.com/gengyf/p/11600205.html
Recommended