Link:
#include <stdio.h>int main(){ puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/46506883");}
Exercises
First build the virtual tree and then DP on the virtual tree.
The process is simple.
Find each virtual tree node first i Next to the nearest query node n e a r i (Because some LCA has also been added to the virtual tree, so the virtual tree node is not all the inquiry node, er afraid you do not understand, but in fact this is nonsense qwq. )
Then for each chain [l,R] Find [Nea r l ,Nea r R ] The midpoint, then the two sides casually give a give just fine.
Code:
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define LOGN#define N 301000#define TI tree[i]#define PI Point[i]#define INF 0x3f3f3f3fusing namespace STD;structeli{intV,n;} e[n<<1];inthead[n],cnt;inline voidAddintUintV) {e[++cnt].v=v; E[cnt].n=head[u]; head[u]=cnt;}intF[n][logn],dep[n];intSize[n],dfn[n];intInitintXintP//Dispose of the above four arrays{intI,u,v; dfn[x]=++cnt,size[x]=1; f[x][0]=p,dep[x]=dep[p]+1; for(i=1; f[x][i-1];i++) f[x][i]=f[f[x][i-1]][i-1]; for(I=HEAD[X];I;I=E[I].N) {v=e[i].v;if(v==p)Continue; Size[x]+=init (V,X); }returnSIZE[X];}//will not explode stack I do not want to consider. And don't want to. Because I don't want to say it two times. intGetlca (intXintY//Get an LCA of X, y{if(Dep[x]<dep[y]) swap (x, y); for(inti=logn-1; ~i;i--)if(Dep[f[x][i]]>=dep[y]) x=f[x][i];if(x==y)returnX for(inti=logn-1; ~i;i--)if(F[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];returnf[x][0];}intFindintXintD//Find the ancestor of the depth of X for D{ for(inti=logn-1; ~i;i--)if(Dep[f[x][i]]>=d) x=f[x][i];returnx;}intN,m,p,rec[n];BOOLCMP_DFN (intAintb) {returnDFN[A]<DFN[B];}intStk[n],top,val[n],ans[n];intPoint[n],tree[n],fa[n];intNear[n],dis[n],len[n];voidSolve () {intI,x,s; cnt=top=0;scanf("%d", &p); for(i=1; i<=p;i++) {scanf("%d", &PI); Tree[++cnt]=pi;///rec:point[] was sorted and had to be saved one downRec[i]=near[pi]=pi; dis[pi]=ans[pi]=0; } sort (point+1, point+p+1, CMP_DFN); for(i=1; i<=p;i++)//Build virtual tree{if(!top) fa[stk[++top]=pi]=0;Else{intLca=getlca (Pi,stk[top]); for(;d ep[stk[top]]>dep[lca];top--)if(dep[stk[top-1]]<=DEP[LCA]) Fa[stk[top]]=lca;if(STK[TOP]!=LCA) {Fa[lca]=stk[top]; Stk[++top]=tree[++cnt]=lca; near[lca]=0, Dis[lca]=inf; } Fa[stk[++top]=pi]=lca; }} sort (tree+1, tree+cnt+1, CMP_DFN); for(i=1; i<=cnt;i++) {Val[ti]=size[ti]; Len[ti]=dep[ti]-dep[fa[ti]]; } for(i=cnt;i>=2; i--)//Find the nearest demand point for each virtual tree node{if(Dis[fa[ti]]>dis[ti]+len[ti]) {Dis[fa[ti]]=dis[ti]+len[ti]; Near[fa[ti]]=near[ti]; }Else if(Dis[fa[ti]]==dis[ti]+len[ti]) near[fa[ti]]=min (Near[fa[ti]],near[ti]); } for(i=2; i<=cnt;i++)//Find the nearest demand point for each virtual tree node{if(Dis[ti]>dis[fa[ti]]+len[ti]) {Dis[ti]=dis[fa[ti]]+len[ti]; Near[ti]=near[fa[ti]]; }Else if(Dis[ti]==dis[fa[ti]]+len[ti]) near[ti]=min (Near[ti],near[fa[ti]); } for(i=1; i<=cnt;i++)//Each chain to find the midpoint to process{if(i==1) Ans[near[ti]]+=n-size[ti];Else{X=find (ti,dep[fa[ti]]+1); S=size[x]-size[ti]; VAL[FA[TI]]-=SIZE[X];if(Near[fa[ti]]==near[ti]) ans[near[ti]]+=s;Else{intnum=dis[fa[ti]]+dis[ti]+len[ti]+1;intmid=dep[ti]-((num+1)/2-dis[ti]) +1;if((num&1) &&near[ti]>near[fa[ti]) mid++; X=size[x]-size[find (Ti,mid)]; Ans[near[fa[ti]]]+=x; Ans[near[ti]]+=s-x; } } } for(i=1; i<=cnt;i++) Ans[near[ti]]+=val[ti]; for(i=1; i<=p;i++)printf("%d", Ans[rec[i]]);puts("");}intMain () {intI,j,k;intA,b,c;scanf("%d", &n); for(i=1; i<n;i++) {scanf("%d%d", &a,&b); Add (A, B), add (B,a); }cnt=0; Init1,0); for(scanf("%d", &m); m--;) Solve ();return 0;}
"BZOJ3572" "Hnoi2014" World Tree Virtual tree