【GDSOI2017】 中学生数据结构题

来源:互联网 发布:网络信息特点有哪些 编辑:程序博客网 时间:2024/04/26 02:07

Description

这里写图片描述

Data Constraint

这里写图片描述

Solution

看到SHIFT操作,很显然就想到了splay中的翻转操作,还在树上,我们就考虑LCT。
但想了一会我们发现,直接SHIFT操作会破坏LCT树中的点与点的连接关系。
于是我们考虑维护两颗LCT,一颗维护树的形态,一颗维护树中的权值,保证对于一个维护树的形态的LCT中的splay,维护树中权值的LCT中都有一个大小相同的与之对应的splay,且这两个splay的中序遍历恰好使得每个编号都对应回自己的权值。对于一个SHIFT,我们就只翻转权值树中的点,这样就保证了在翻转同时不破坏树的形态。
那问题又来了,我们如何维护这两个LCT树之间的关系?对于一个编号,我们如何知道他在权值LCT中的位置呢?
对于每个操作,如access,makeroot等,我们可以同时对这两个LCT进行操作。那么我们对于一个编号,由于保证了对于一个编号splay的中序遍历,都有一个权值splay中的中序遍历与之相同,我们可以维护这个编号splay在权值LCT中的splay是哪个,然后我们按照当前编号在编号LCT中的splay的中序遍历的位置x,在对应的权值LCT中按中序遍历找一下第x个就好了。

Code

#include<iostream>#include<cmath>#include<cstring>#include<cstdio>#include<algorithm>#define ll long longusing namespace std;const int maxn=2e5+5;int fa[maxn],pfa[maxn],f[maxn][2],bz[maxn],bz3[maxn],size[maxn],p[maxn];int first[maxn],last[maxn],next[maxn],fa1[maxn],g[maxn][2],bz1[maxn];int n,m,i,t,j,k,l,x,y,num,xx,yy,d[maxn],bz4[maxn];ll sum[maxn],bz2[maxn],size1[maxn],b[maxn],z;char s[20];void bfs(){    int i=0,j=1,x;d[1]=1;    while (i<j){        x=d[++i];size1[x]=size[x]=1;p[x]=x;        for (t=first[x];t;t=next[t])            if (!size[last[t]]) d[++j]=last[t],pfa[d[j]]=x;    }}void change1(int x){    int y=g[x][0],z=g[x][1];    if (bz1[x]) swap(g[y][0],g[y][1]),swap(g[z][0],g[z][1]),bz1[y]=1-bz1[y],bz1[z]=1-bz1[z],bz1[x]=0;    if (bz2[x]) b[y]+=bz2[x],b[z]+=bz2[x],sum[y]+=size1[y]*bz2[x],sum[z]+=size1[z]*bz2[x],bz2[y]+=bz2[x],bz2[z]+=bz2[x],bz2[x]=0;}bool son(int x){return f[fa[x]][1]==x;}bool son1(int x){return g[fa1[x]][1]==x;}void change(int x){    int y=f[x][0],z=f[x][1];    if (bz[x]) swap(f[y][0],f[y][1]),swap(f[z][0],f[z][1]),bz[y]=1-bz[y],bz[z]=1-bz[z],bz[x]=0;    if (bz3[x]) p[y]=bz3[y]=p[z]=bz3[z]=bz3[x],bz3[x]=0;}void move(int x,int y){    while (x!=y) d[++d[0]]=x,x=fa[x];    for (;d[0];d[0]--) change(d[d[0]]);}void move1(int x,int y){    while (x!=y) d[++d[0]]=x,x=fa1[x];    for (;d[0];d[0]--) change1(d[d[0]]);}void rotate(int x){    size[x]=size[f[x][0]]+size[f[x][1]]+1;}void rotate1(int x){    int y=g[x][0],z=g[x][1];size1[x]=size1[y]+size1[z]+1;sum[x]=sum[y]+sum[z]+b[x];}void make(int x){    int y=fa[x],z=son(x);    f[fa[y]][son(y)]=x;fa[x]=fa[y];swap(pfa[x],pfa[y]);    fa[f[y][z]=f[x][1-z]]=y;fa[f[x][1-z]=y]=x;rotate(y);rotate(x);}void make1(int x){    int y=fa1[x],z=son1(x);    g[fa1[y]][son1(y)]=x;fa1[x]=fa1[y];    fa1[g[y][z]=g[x][1-z]]=y;fa1[g[x][1-z]=y]=x;rotate1(y);rotate1(x);}int splay(int x,int y){    move(x,y);    while (fa[x]!=y){        if (fa[fa[x]]!=y)            if (son(x)==son(fa[x])) make(fa[x]);            else make(x);        make(x);    }}int splay1(int x,int y){    move1(x,y);    while (fa1[x]!=y){        if (fa1[fa1[x]]!=y)            if (son1(x)==son1(fa[x])) make1(fa1[x]);            else make1(x);        make1(x);    }}int find2(int x,int sum){    change1(x);    while (sum!=size1[g[x][0]]+1){        if (size1[g[x][0]]+1<sum) sum-=size1[g[x][0]]+1,x=g[x][1];        else x=g[x][0];        change1(x);    }    return x;}int find(int x){    splay(x,0);    return find2(p[x],size[f[x][0]]+1);}void access(int x,int xx){    int y=0,yy=0;splay(x,0);    while (x){        splay1(xx,0);        fa[f[x][1]]=0;pfa[f[x][1]]=x;p[f[x][1]]=bz3[f[x][1]]=g[xx][1];fa[f[x][1]=y]=x;pfa[y]=0;rotate(x);        fa1[g[xx][1]]=0;fa1[g[xx][1]=yy]=xx;rotate1(xx);        y=x,x=pfa[x];yy=xx;if (x)xx=find(x);    }}void makeroot(int xx,int x){    access(x,xx);splay(x,0);    bz[x]=1-bz[x];swap(f[x][0],f[x][1]);splay1(xx,0);bz1[xx]=1-bz1[xx];swap(g[xx][0],g[xx][1]);p[x]=bz3[x]=xx;}void lian(int x,int y){    last[++num]=y;next[num]=first[x];first[x]=num;}int main(){    freopen("shift.in","r",stdin);freopen("shift.out","w",stdout);    scanf("%d",&n);    for (i=1;i<n;i++)        scanf("%d%d",&x,&y),lian(x,y),lian(y,x);    bfs();    scanf("%d\n",&m);    for (i=1;i<=m;i++){        scanf("%s%d%d",s+1,&x,&y);        xx=find(x);yy=find(y);        if (s[1]=='A'){            scanf("%lld",&z);            makeroot(xx,x);            access(y,yy);            splay1(xx,0);splay(x,0);p[x]=bz3[x]=xx;            bz2[xx]+=z;sum[xx]+=z*size1[xx];b[xx]+=z;        }else if (s[1]=='Q'){            makeroot(xx,x);            access(y,yy);splay1(xx,0);splay(x,0);            printf("%lld\n",sum[xx]);p[x]=bz3[x]=xx;        }else{            makeroot(xx,x);access(y,yy);splay1(yy,0);swap(g[yy][0],g[yy][1]);splay(y,0);p[y]=bz3[y]=yy;        }        scanf("\n");    }}
原创粉丝点击