题意:求 $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 }