bzoj3159: 决战

来源:互联网 发布:怎么积累淘宝关注人数 编辑:程序博客网 时间:2024/04/28 18:17

这道题真是让我对LCT有了新的认识啊!

题意大概就是实现一颗树,支持路径翻转!然后我一脸懵逼地想到了splay,然后不会。

其实只要一个LCT就可以了,再额外开一颗splay记录prefer路径上的值,然后翻转就是MakeRoot+splay+reverLCT+reverSplay,然后就好了。。。

LCt一行splay真是神奇啊。。。

#include<iostream>#include<cstdio>#define N 50005#define ll long longusing namespace std;int n,m,x,y,z;int Fa[N],C[N][2],Sz[N];ll Val[N],Pls[N],Rev[N],Mx[N],Mn[N],Sm[N];//这是一颗记录值的splayint fa[N],c[N][2],size[N],Rt[N],rev[N];//这是一颗记录父子关系的LCT//----------------splay------------------void Rever(int x){Rev[x]^=1;swap(C[x][0],C[x][1]);}void Add(int x,int y){Val[x]+=y;Pls[x]+=y;Mx[x]+=y;Mn[x]+=y;Sm[x]+=Sz[x]*y;}void Up(int x){int l=C[x][0],r=C[x][1];Sz[x]=1;Sm[x]=Mx[x]=Mn[x]=Val[x];if (l) Sz[x]+=Sz[l],Sm[x]+=Sm[l],Mx[x]=max(Mx[x],Mx[l]),Mn[x]=min(Mn[x],Mn[l]);if (r) Sz[x]+=Sz[r],Sm[x]+=Sm[r],Mx[x]=max(Mx[x],Mx[r]),Mn[x]=min(Mn[x],Mn[r]);}void Down(int x){int l=C[x][0],r=C[x][1];if (Rev[x]) Rever(l),Rever(r),Rev[x]=0;if (Pls[x]) Add(l,Pls[x]),Add(r,Pls[x]),Pls[x]=0;}void Pd(int x){if (Fa[x]) Pd(Fa[x]);Down(x);}void Ro(int x){int y=Fa[x],z=Fa[y],l=C[y][0]!=x,r=l^1;if(z)C[z][C[z][1]==y]=x;Fa[x]=z;Fa[y]=x;Fa[C[x][r]]=y;C[y][l]=C[x][r];C[x][r]=y;Up(y);Up(x);}void Splay(int x,int k,int y=0){for (Pd(x);Fa[x]!=k;Ro(x))if (Fa[y=Fa[x]]!=k) Ro(C[y][0]==x^C[Fa[y]][0]==y?x:y);}int Rank(int x,int k){Down(x);if (k==Sz[C[x][0]]+1) return x;if (k<=Sz[C[x][0]]) return Rank(C[x][0],k);return Rank(C[x][1],k-Sz[C[x][0]]-1);}void split(int &x,int &y,int k){int t=Rank(x,k);Splay(t,0);x=t;y=C[t][1];Fa[y]=C[t][1]=0;Up(x);}int merge(int x,int y){int t=Rank(x,Sz[x]);Splay(t,0);C[t][1]=y;Fa[y]=t;Up(t);return t;}//-----------------LCT-------------------bool IR(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}void down(int x){if (rev[x]){swap(c[x][0],c[x][1]);rev[x]=0,rev[c[x][0]]^=1,rev[c[x][1]]^=1;}}void pd(int x){if (!IR(x))pd(fa[x]);down(x);}void up(int x){size[x]=size[c[x][0]]+size[c[x][1]]+1;}void rotate(int x){int y=fa[x],z=fa[y],l=c[y][0]!=x,r=l^1;if(!IR(y))c[z][c[z][1]==y]=x;fa[x]=z;fa[y]=x;fa[c[x][r]]=y;c[y][l]=c[x][r];c[x][r]=y;up(y);up(x);}void splay(int x,int y=0){for (pd(x),y=x;!IR(y);y=fa[y]);swap(Rt[x],Rt[y]);for (;!IR(x);rotate(x))if (!IR(y=fa[x])) rotate(c[y][0]==x^c[fa[y]][0]==y?x:y);}void acc(int x){for(int t=0;x;t=x,x=fa[x]){splay(x);if (c[x][1]) split(Rt[x],Rt[c[x][1]],size[c[x][0]]+1);if (t) Rt[x]=merge(Rt[x],Rt[t]),Rt[t]=0;c[x][1]=t;fa[t]=x;up(x);}}void MRt(int x){acc(x);splay(x);rev[x]^=1;Rever(Rt[x]);}void link(int x,int y){MRt(x);fa[x]=y;}void inv(int x,int y){MRt(x);acc(y);splay(y);Rever(Rt[y]);}void add(int x,int y,int z){MRt(x);acc(y);splay(y);Add(Rt[y],z);}ll Qsum(int x,int y){MRt(x);acc(y);splay(y);return Sm[Rt[y]];}ll Qmax(int x,int y){MRt(x);acc(y);splay(y);return Mx[Rt[y]];}ll Qmin(int x,int y){MRt(x);acc(y);splay(y);return Mn[Rt[y]];}int main(){scanf("%d%d%*d",&n,&m);for (int i=1;i<=n;i++) Rt[i]=i,Sz[i]=size[i]=1;for (int i=1;i<n;i++)scanf("%d%d",&x,&y),link(x,y);for(char p[10];m--;){scanf("%s%d%d",p,&x,&y);if (p[0]=='S') printf("%lld\n",Qsum(x,y));else if (p[1]=='a')printf("%lld\n",Qmax(x,y));else if (p[1]=='i')printf("%lld\n",Qmin(x,y));else if (p[2]=='v')inv(x,y);else scanf("%d",&z),add(x,y,z);}//system("pause");}


1 0