splay的区间操作

又是一个晚上,美好的青春都用来调试了

其实正解和我原来想的非常不一样,我本来是想用下标表示下标,后来突然发现不对,如果你下标不变,交换的时候只交换值的话,左右子树不一样大,就出问题了。

后来就连着下标一起交换,诶诶诶那这样你怎么让我找点啊,我本身建树的时候优先级就是按照下标来的啊。

后来一拍脑袋想起来中序遍历是不变的,可以通过查找siz的大小来解决原序列的下标问题,不敢相信这复杂度去翻了一下标程,居然就是这样的,这真的让我很无语。

还有我好像真的不擅长指针啊,标程看得我头都大了。 

#include<cstdio>

#include<cstring>
#include<algorithm>
#define maxn 100007
int son[maxn][2],fa[maxn],weight[maxn],siz[maxn],rr[maxn],root=0,counter=0;
inline void clear()
{
memset(son,0,sizeof(int));
memset(fa,0,sizeof(int));
memset(weight,0,sizeof(int));
memset(siz,0,sizeof(int));
memset(rr,0,sizeof(int));
}
inline void updata(int now)
{siz[now]=1+siz[son[now][0]]+siz[son[now][1]];}
inline void swap(int now)
{
int t=son[now][0];
son[now][0]=son[now][1],son[now][1]=t;
}
inline void pushdown(int now)
{
if(rr[now])//注意已经打标记的点儿子已经交换过
{
if(son[now][0]){rr[son[now][0]]=!rr[son[now][0]];swap(son[now][0]);}
if(son[now][1]){rr[son[now][1]]=!rr[son[now][1]];swap(son[now][1]);}
rr[now]=0;
}
}
inline int askflag(int now)
{if(son[fa[now]][0]==now)return 0;return 1;}
inline void rorate(int now)
{
int f=fa[now],flag=askflag(now);
if(f!=root)fa[now]=fa[f],son[fa[f]][askflag(f)]=now;
else root=now,fa[now]=-1;
if(f)pushdown(f);pushdown(now); //先下放父亲
if(son[now][!flag])fa[son[now][!flag]]=f;
son[f][flag]=son[now][!flag];
fa[f]=now;
son[now][!flag]=f;
updata(f),updata(now);
}
inline void splay(int now,int tar)
{
int temp=fa[tar];
while(temp!=fa[now]) //因为tar会被换下来,fa[tar]是变化的
{
if(fa[now]!=root&&fa[fa[now]]!=root)
 if(askflag(fa[now])!=askflag(now))rorate(fa[now]);
 else rorate(now);
rorate(now);
}
}
inline int find(int now,int k)
{
if(rr[now])//每一次查询都要先下放标记
{
rr[now]=0;
if(son[now][0])rr[son[now][0]]=!rr[son[now][0]],swap(son[now][0]);
if(son[now][1])rr[son[now][1]]=!rr[son[now][1]],swap(son[now][1]);
}
if(siz[son[now][0]]+1==k)return now;
if(siz[son[now][0]]+1>k)return find(son[now][0],k);
else return find(son[now][1],k-1-siz[son[now][0]]);
}
inline void cut(int l,int r,int c)
{
int temp,t;
splay(find(root,l-1),root);
splay(find(root,r+1),son[root][1]);
temp=son[son[root][1]][0];
splay(find(root,c),root);
splay(t=find(root,c+1),son[root][1]);
son[fa[temp]][askflag(temp)]=0;//splay之前绝对不能清零,要不siz会出错
fa[temp]=t;
son[t][0]=temp;
return ;
}
inline void re(int l,int r)
{
splay(find(root,l-1),root);
splay(find(root,r+1),son[root][1]);
int temp=son[son[root][1]][0];
rr[temp]=!rr[temp];
swap(temp);
}
inline int getpos(int now,int sx)
{
if(now+1==sx)return now;
if(now+1>sx)return(son[now][0],sx);
if(now+1<sx)return(son[now][1],sx);
}
inline void insert(int val)
{
int f=getpos(root,++counter);
if(f)son[f][1]=counter,fa[counter]=f;
else root=counter,fa[counter]=-1;
weight[counter]=val;
updata(counter);
if(f)updata(f);
splay(counter,root); 
}
inline void printff(int now)
{
if(son[now][0])printff(son[now][0]);
printf("%d ",weight[now]);
if(son[now][1])printff(son[now][1]);
}
int main()
{
int n,m,temp,x,y,z;
char ss[10],c;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&temp);
insert(temp);
}
for(int i=1;i<=m;i++)
{
scanf("%s",ss);
scanf("%d%d",&x,&y);
c=ss[0];
if(c=='R') re(x,y);
if(c=='C') scanf("%d",&z),cut(x,y,z);
}
printff(root);
}
posted @ 2017-04-16 17:48  OcahIBye  阅读(225)  评论(0编辑  收藏  举报