Lowest Common Ancestor

题意:求 $f(i) = sum_{j=1}^{i-1}{w(LCA(i,j))}$,输出所有的$f(i)$

解法:

首先,如果题目变为有K个关键点,问$f(i) = sum_{p∈{K}} {w(LCA(i,K))}$做法显然,只要dfs一遍即可。

考虑cdq分治,每一次对于区间[L,R],将[L,R]的点建虚树,而后对其dfs,求[L,mid]的关键点对[mid+1,R]的答案的贡献

注意用RMQ_LCA,O(1),不然会TLE。

  1 #include <iostream>
  2 #include <iostream>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <algorithm>
  6 
  7 #define N 200010
  8 #define p E[i].x
  9 #define LL long long
 10 
 11 using namespace std;
 12 
 13 struct edge
 14 {
 15     int x,to;
 16 }E[N];
 17 
 18 int n,totE,tot2;
 19 int g[N],dfsn[N],w[N],d[N],L[N],fa[N];
 20 int dfsn2[N<<1],mind[N<<1][20],maxt[N<<1];
 21 LL ansv[N];
 22 
 23 void addedge(int x,int y)
 24 {
 25     E[++totE]=(edge){y,g[x]}; g[x]=totE;
 26 }
 27 
 28 void dfs(int x)
 29 {
 30     dfsn[x]=++dfsn[0];
 31     for(int i=g[x];i;i=E[i].to)
 32     {
 33         d[p]=d[x]+1;
 34         dfs(p);
 35     }
 36 }
 37 
 38 void dfs2(int x)
 39 {
 40     dfsn2[++tot2]=x;
 41     mind[tot2][0]=x;
 42     L[x]=tot2;
 43     for(int i=g[x];i;i=E[i].to)
 44     {
 45         dfs2(p);
 46         dfsn2[++tot2]=x;
 47         mind[tot2][0]=x;
 48     }
 49 }
 50 
 51 inline int LCA(int x,int y)
 52 {
 53     int l=L[x],r=L[y];
 54     if(x==y) return x;
 55     if(l>r) swap(l,r);
 56     int t=maxt[r-l+1];
 57     x = mind[l][t];
 58     y = mind[r-(1<<t)+1][t];
 59     if(d[x]<d[y]) return x;
 60     else return y;
 61 }
 62 
 63 namespace virtual_tree
 64 {
 65     edge E[N];
 66     
 67     int tot,totE,ed;
 68     int g[N],tmp[N],id[N],num[N],q[N],siz[N];
 69     
 70     void addedge(int x,int y)
 71     {
 72         if(!id[x])
 73         {
 74             id[x]=++tot;
 75             num[tot]=x;
 76         }
 77         if(!id[y])
 78         {
 79             id[y]=++tot;
 80             num[tot]=y;
 81         }
 82         x=id[x];
 83         y=id[y];
 84         E[++totE]=(edge){y,g[x]};
 85         g[x]=totE;
 86     }
 87     
 88     bool cmp(int a,int b)
 89     {
 90         return dfsn[a]<dfsn[b];
 91     }
 92     
 93     void dfs(int x)
 94     {
 95         for(int i=g[x];i;i=E[i].to)
 96         {
 97             dfs(p);
 98             siz[x]+=siz[p];
 99         }
100     }
101     
102     void build_tree()
103     {
104         for(int t=1;t<=tmp[0];t++)
105         {
106             int i=tmp[t];
107             int lca=LCA(i,q[ed]);
108             if(lca==q[ed]) q[++ed]=i;
109             else
110             {
111                 while(ed>1 && dfsn[q[ed-1]]>dfsn[lca])
112                     addedge(q[ed-1],q[ed]), ed--;
113                 if(dfsn[q[ed]]>dfsn[lca])
114                     addedge(lca,q[ed]), ed--;
115                 if(dfsn[q[ed]]<dfsn[lca]) q[++ed]=lca;
116                 q[++ed]=i;
117             }
118         }
119         while(ed>1)
120             addedge(q[ed-1],q[ed]), ed--;
121     }
122     
123     void dfs2(int x,int mid,int r,LL now)
124     {
125         if(num[x]<=r && num[x]>mid) ansv[num[x]] += now + siz[x]*(LL)w[num[x]];
126         for(int i=g[x];i;i=E[i].to)
127             dfs2(p,mid,r,now + (siz[x]-siz[p])*(LL)w[num[x]]);
128     }
129     
130     void solve(int l,int r,int mid)
131     {
132         totE=0;
133         for(int i=1;i<=tot;i++)
134         {
135             id[num[i]]=0;
136             g[i]=0;
137             num[i]=0;
138             siz[i]=0;
139         }
140         tot=1;
141         num[tot]=id[1]=1;
142         q[ed=1]=1;
143         tmp[0]=0;
144         for(int i=l;i<=r;i++)
145         {
146             if(i!=1)
147             {
148                 num[++tot]=i;
149                 id[i]=tot;
150                 tmp[++tmp[0]]=i;
151             }
152             if(i<=mid) siz[id[i]]=1;
153         }
154         sort(tmp+1,tmp+tmp[0]+1,cmp);
155         build_tree();
156         dfs(1);
157         dfs2(1,mid,r,0LL);
158     }
159 };
160 
161 void cdq(int l,int r)
162 {
163     if(l==r) return;
164     int mid=(l+r)>>1;
165     cdq(l,mid);
166     cdq(mid+1,r);
167     virtual_tree::solve(l,r,mid);
168 }
169 
170 int main()
171 {
172 //    freopen("test.txt","r",stdin);
173     while(~scanf("%d",&n))
174     {
175         for(int i=1;i<=n;i++) g[i]=0;
176         totE=0;
177         for(int i=1;i<=n;i++) scanf("%d",&w[i]);
178         for(int i=2;i<=n;i++)
179         {
180             scanf("%d",&fa[i]);
181             addedge(fa[i],i);
182         }
183         dfsn[0]=0;
184         tot2=0;
185         d[1]=1;
186         dfs(1);
187         dfs2(1);
188         int j=0;
189         for(int i=1;i<=tot2;i++)
190         {
191             maxt[i]=j;
192             if(i==(1<<(j+1))) j++;
193         }
194         for(int t=1;t<20;t++)
195             for(int i=1;i+(1<<t)-1<=tot2;i++)
196             {
197                 int x=mind[i][t-1];
198                 int y=mind[i+(1<<(t-1))][t-1];
199                 if(d[x]<d[y]) mind[i][t]=x;
200                 else mind[i][t]=y;
201             }
202         for(int i=1;i<=n;i++) ansv[i]=0;
203         cdq(1,n);
204         for(int i=2;i<=n;i++) printf("%lld
",ansv[i]);
205     }
206     return 0;
207 }
View Code
原文地址:https://www.cnblogs.com/lawyer/p/6443605.html