zjoi2006 书架
动态序列的维护问题
也可以用文艺平衡树的方式来简化操作
#include <iostream>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <cstdlib>
using namespace std;
const int N=2e5+10;
int read()
{
int x=0,f=0,c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return f?-x:x;
}
int sz[N],lch[N],rch[N],rnd[N],val[N],pos[N],fa[N];
int root,rx,ry,rz,cnt;
int n,m;
void SWAP(int x,int y)
{
swap(val[x],val[y]);
pos[val[x]]=x; pos[val[y]]=y;
}
int _new(int x){sz[++cnt]=1; rnd[cnt]=rand(); val[cnt]=x; pos[x]=cnt; return cnt;}
void upd(int x){ sz[x]=sz[lch[x]]+sz[rch[x]]+1;}
//记录父亲的做法
void split(int now,int k,int &x,int &y,int fax,int fay)
{
if(!now){ x=y=0; return;}
if(k>=sz[lch[now]]+1){ x=now; fa[x]=fax; split(rch[now],k-sz[lch[now]]-1,rch[x],y,x,fay);}
else {y=now; fa[y]=fay; split(lch[now],k,x,lch[y],fax,y);}
upd(now);
}
int merge(int x,int y)
{
if(!x||!y) return x+y;
if(rnd[x]<rnd[y]){ rch[x]=merge(rch[x],y); fa[rch[x]]=x; upd(x); return x;}
else { lch[y]=merge(x,lch[y]); fa[lch[y]]=y; upd(y); return y;}
}
//需要获取编号为x的书本的位置
//但是平衡树中不记录下标
//但是我们只需要在logn的时间里获得位置即可 因此暴力向上跳就可以
int findp(int x,int rt)
{
int p=pos[x],ret=0;
ret+=sz[lch[p]]+1;
while(p!=rt)
{
if( rch[fa[p]]==p ) ret+=sz[lch[fa[p]]]+1;
p=fa[p];
}
return ret;
}
//调试的时候不要拿完全二叉树来调试
//向着左上方向走的才会被记入答案中
int findk(int k,int rt)
{
int now=rt;
while(1)
{
int lsz=sz[lch[now]],rsz=sz[rch[now]];
if(k==lsz+1) return now;
else if(k<lsz+1) now=lch[now];
else now=rch[now],k=k-lsz-1;
}
}
void Top(int x)
{
int p=findp(x,root);
split(root,p,rx,rz,0,0);
split(rx,p-1,rx,ry,0,0);//连续分裂的根的问题
root=merge( merge(_new(x),rx),rz );
}
void Bottom(int x)
{
int p=findp(x,root);
split(root,p,rx,rz,0,0);
split(rx,p-1,rx,ry,0,0);
root=merge( merge(rx,rz),_new(x) );
}
void Insert(int x,int t)
{
if(t==0) return;
int p=findp(x,root);
int q=findk(p+t,root);
SWAP(pos[x],q);
}
int main()
{
srand(1);
n=read(); m=read();
for(int i=1;i<=n;i++)
{
int x=read();
root=merge(root,_new(x));
}
for(int i=1;i<=m;i++)
{
char s[10]; scanf("%s",s);
char c=s[0]; int x=read();
if(c=='T') Top(x);
else if(c=='B') Bottom(x);
else if(c=='I') Insert(x,read());
else if(c=='A') printf("%d\n",findp(x,root)-1);
else printf("%d\n",val[findk(x,root)]);
}
}

浙公网安备 33010602011771号