BZOJ3757 苹果树
一道挺好的树上莫队板子题,可惜存在版权无法提交了。
这里给出代码供大家参考,分块操作类似于王室联盟,转成序列后和普通莫队一样。
By:大奕哥
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e5+5; 4 int d[N],fa[N][20],bel[N],size[N],dfn[N],col[N],ans[N],p[N],head[N]; 5 int n,m,sum,idx,cnt,B,num,top,s[N]; 6 bool v[N]; 7 struct node{ 8 int to,nex; 9 }e[N<<1]; 10 void add(int x,int y) 11 { 12 e[++cnt].nex=head[x];e[cnt].to=y;head[x]=cnt; 13 } 14 struct quer{ 15 int x,y,a,b,id; 16 bool operator<(const quer &b)const{ 17 return bel[x]<bel[b.x]||(bel[x]==bel[b.x]&&dfn[y]<dfn[b.y]); 18 } 19 }q[N]; 20 void dfs(int x) 21 { 22 dfn[x]=++idx;s[++top]=x; 23 for(int i=1;i<=16;++i) 24 fa[x][i]=fa[fa[x][i-1]][i-1]; 25 for(int i=head[x];i;i=e[i].nex) 26 { 27 int y=e[i].to; 28 if(y==fa[x][0])continue; 29 fa[y][0]=x;d[y]=d[x]+1; 30 dfs(y); 31 size[x]+=size[y]; 32 if(size[x]>=B) 33 { 34 num++; 35 for(int k=1;k<=size[x];++k) 36 bel[s[top--]]=num; 37 size[x]=0; 38 } 39 } 40 size[x]++; 41 } 42 int lca(int x,int y) 43 { 44 if(d[x]<d[y])swap(x,y); 45 int tmp=d[x]-d[y]; 46 for(int i=0;i<=16;++i) 47 if(tmp&(1<<i))x=fa[x][i]; 48 for(int i=16;i>=0;--i) 49 { 50 if(fa[x][i]!=fa[y][i]) 51 { 52 x=fa[x][i]; 53 y=fa[y][i]; 54 } 55 } 56 return x==y?x:fa[x][0]; 57 } 58 void reverse(int x) 59 { 60 if(!v[x]){v[x]=1;p[col[x]]++;if(p[col[x]]==1)sum++;} 61 else {v[x]=0;p[col[x]]--;if(p[col[x]]==0)sum--;} 62 return; 63 } 64 void solve(int x,int y) 65 { 66 while(x!=y) 67 { 68 if(d[x]<d[y])swap(x,y); 69 reverse(x);x=fa[x][0]; 70 } 71 return; 72 } 73 int main() 74 { 75 scanf("%d%d",&n,&m); 76 B=sqrt(n);int x,y,rt; 77 for(int i=1;i<=n;++i)scanf("%d",&col[i]); 78 for(int i=1;i<=n;++i) 79 { 80 scanf("%d%d",&x,&y); 81 if(!x)rt=y;else if(!y)rt=x; 82 else add(x,y),add(y,x); 83 } 84 dfs(rt);num++; 85 while(top)bel[s[top--]]=num; 86 for(int i=1;i<=m;++i) 87 { 88 scanf("%d%d",&q[i].x,&q[i].y); 89 if(dfn[q[i].x]>dfn[q[i].y])swap(q[i].x,q[i].y); 90 q[i].id=i; 91 scanf("%d%d",&q[i].a,&q[i].b); 92 } 93 sort(q+1,q+1+m); 94 int z=lca(q[1].x,q[1].y); 95 solve(q[1].x,q[1].y); 96 reverse(z);ans[q[1].id]=sum; 97 if(p[q[1].a]&&p[q[1].b]&&q[1].a!=q[1].b)ans[q[1].id]--; 98 reverse(z); 99 for(int i=2;i<=m;++i) 100 { 101 int z=lca(q[i].x,q[i].y); 102 solve(q[i-1].x,q[i].x); 103 solve(q[i-1].y,q[i].y); 104 reverse(z);ans[q[i].id]=sum; 105 if(p[q[i].a]&&p[q[i].b]&&q[i].a!=q[i].b)ans[q[i].id]--; 106 reverse(z); 107 } 108 for(int i=1;i<=m;++i)printf("%d\n",ans[i]); 109 return 0; 110 }
生命中真正重要的不是你遭遇了什么,而是你记住了哪些事,又是如何铭记的。