[ZJOI2006]书架

fhq treap

开个minnmaxn作排序标准

置顶就更新val=--minn,垫底就更新val=++maxn

改变位置就相当于找前驱后继swap(val1,val2)

找排名为k的编号就是二叉查找树的模板

找编号为k前面的书个数就拆树取左边的siz

#include"cstdio"
#include"cstring"
#include"iostream"
#include"algorithm"
#include"ctime"
using namespace std;

const int MAXN=8e4+5;

int n,m,cnt,minn,root,maxn;
int siz[MAXN],sn[MAXN][2];
int rev[MAXN],val[MAXN];
char ch[16];

int cret(int x,int v)
{
	siz[x]=1;
	val[x]=v;
	rev[x]=rand();
	sn[x][0]=sn[x][1]=0;
	return x;
}

int un(int x,int y)
{
	if(!x||!y) return x|y;
	if(rev[x]<rev[y]){
		sn[x][1]=un(sn[x][1],y);
		siz[x]=siz[sn[x][0]]+siz[sn[x][1]]+1;
		return x;
	}sn[y][0]=un(x,sn[y][0]);
	siz[y]=siz[sn[y][0]]+siz[sn[y][1]]+1;
	return y;
}

void dro(int k,int v,int &x,int &y)
{
	if(!k){x=y=0;return;}
	if(val[k]<=v) x=k,dro(sn[k][1],v,sn[k][1],y);
	else y=k,dro(sn[k][0],v,x,sn[k][0]);
	siz[k]=siz[sn[k][0]]+siz[sn[k][1]]+1;
	return;
}

int rnk(int k,int v)
{
	if(v<=siz[sn[k][0]]) return rnk(sn[k][0],v);
	if(v==siz[sn[k][0]]+1) return k;
	return rnk(sn[k][1],v-siz[sn[k][0]]-1);
}

void debug()
{
	for(int i=1;i<=n;++i) printf("%d ",rnk(root,i));
	puts("");
}

void Tp()
{
	int v,x,y,z;scanf("%d",&v);
	dro(root,val[v],x,z),dro(x,val[v]-1,x,y);
	y=un(sn[y][0],sn[y][1]);root=un(un(x,y),z);
	--minn;cret(v,minn);
	dro(root,val[v],x,y);
	root=un(un(x,v),y);
	return;
}

void Bt()
{
	int v,x,y,z;scanf("%d",&v);
	dro(root,val[v],x,z),dro(x,val[v]-1,x,y);
	y=un(sn[y][0],sn[y][1]);root=un(un(x,y),z);
	++maxn;cret(v,maxn);
	dro(root,val[v],x,y);
	root=un(un(x,v),y);
	return;
}

void del(int v)
{
	int x,y,z;
	dro(root,val[v],x,z);dro(x,val[v]-1,x,y);
	y=un(sn[y][0],sn[y][1]);
	root=un(un(x,y),z);
	return;
}

void Ins()
{
	int v,u,x,y,tmp;scanf("%d%d",&v,&u);
	if(!u) return;
	if(u==1) dro(root,val[v],x,y),tmp=rnk(y,1),root=un(x,y);
	else dro(root,val[v]-1,x,y),tmp=rnk(x,siz[x]),root=un(x,y);
	int v1=val[v],v2=val[tmp];
	del(v);del(tmp);
	dro(root,v1,x,y);root=un(un(x,cret(tmp,v1)),y);
	dro(root,v2,x,y);root=un(un(x,cret(v,v2)),y);
	return;
}

void As()
{
	int v,x,y;scanf("%d",&v);
	dro(root,val[v]-1,x,y);
	printf("%d\n",siz[x]);
	root=un(x,y);
	return;
}

void Cas()
{
	int v,x,y;scanf("%d",&v);
	printf("%d\n",rnk(root,v));
	return;
}

int main()
{
	scanf("%d%d",&n,&m);maxn=n;
	for(int i=1;i<=n;++i){
		int v,x,y;scanf("%d",&v);
		dro(root,i,x,y);
		root=un(un(x,cret(v,i)),y);
	}while(m--){
		scanf("%s",ch+1);
		if(ch[1]=='T') Tp();
		else if(ch[1]=='B') Bt();
		else if(ch[1]=='I') Ins();
		else if(ch[1]=='A') As();
		else Cas();
	}return 0;
}
posted @ 2018-12-05 17:32  A·H  阅读(108)  评论(0编辑  收藏  举报