1861: [Zjoi2006]Book 书架

Splay又写挫了。。。。。。。。

回头复习一下维修数列和LCT吧,不然Splay真不会写了。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=80000+5;
const int inf=1e9;
int id[N],ch[N][2],fa[N],a[N],root,sz[N],node,key[N],n,m;
inline void pushup(int x){sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;}
inline void rotate(int x,int &k){
	int y=fa[x],z=fa[y],l=ch[y][1]==x,r=l^1;
	if(y==k)k=x;
	else ch[z][ch[z][1]==y]=x;
	fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
	ch[y][l]=ch[x][r];ch[x][r]=y;
	pushup(y);pushup(x);
}
inline void splay(int x,int &k){
	while(x!=k){
		int y=fa[x],z=fa[y];
		if(y!=k){
			if(ch[y][0]==x^ch[z][0]==y)rotate(x,k);
			else rotate(y,k);
		}
		rotate(x,k);
	}
}
void build(int l,int r,int f){
	if(l>r)return;
	int mid=l+r>>1,now=mid,last=f;
	if(l==r){
		sz[now]=1;
	}else build(l,mid-1,mid),build(mid+1,r,mid);
	key[now]=a[mid];fa[now]=last;pushup(now);
	ch[last][mid>=f]=now;
}
int kth(int x,int k){
	int r=sz[ch[x][0]]+1;
	if(r==k)return x;
	else if(k<r)return kth(ch[x][0],k);
	else return kth(ch[x][1],k-r);
}
void del(int k){
	int x,y,z;
	x=kth(root,k-1);y=kth(root,k+1);
	splay(x,root);splay(y,ch[x][1]);
	z=ch[y][0];ch[y][0]=0;fa[z]=sz[z]=0;
	pushup(y);pushup(x);
}
void move(int k,int val){
	int x,y,z=id[k],rank;
	splay(z,root);rank=sz[ch[z][0]]+1;
	del(rank);
	if(val==inf)x=kth(root,n),y=kth(root,n+1);
	else if(val==-inf)x=kth(root,1),y=kth(root,2);
	else x=kth(root,rank+val-1),y=kth(root,rank+val);
	splay(x,root);splay(y,ch[x][1]);
	sz[z]=1;fa[z]=y;ch[y][0]=z;
	pushup(y);pushup(x);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=2;i<=n+1;i++){
		scanf("%d",&a[i]);id[a[i]]=i;
	}
	build(1,n+2,0);root=n+3>>1;
	char opt[10];int s,t;
	while(m--){
		scanf("%s%d",opt,&s);
		switch(opt[0]){
			case 'T':move(s,-inf);break;
			case 'B':move(s,inf);break;
			case 'I':scanf("%d",&t);move(s,t);break;
			case 'A':splay(id[s],root);printf("%d\n",sz[ch[id[s]][0]]-1);break;
			case 'Q':printf("%d\n",key[kth(root,s+1)]);break;
		}
	}
	return 0;
}


你可能感兴趣的:(1861: [Zjoi2006]Book 书架)