【bzoj1861】[Zjoi2006]Book 书架 splay

splay的另一种应用,维护序列,不再按照权值建平衡树,而是按照下标建平衡树,然后维护一些东西。

题目大意:

1、把编号为S的书放到最上面

2、把编号为S的书放到最下面

3、把编号为S的书前移、后移或者不动

4、询问编号为S的书上面有多少本书

5、询问第S本书的编号

很朴素的平衡树,不需要维护任何东西,直接模拟就好。

记录一下编号为S的书对应的splay上的节点。

1、2、3 删掉这本书,新建一个节点,插入对应位置

4、把对应节点旋转到根,求左子树大小

5、从根开始查找第S小的节点。


#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>
#define inf 1000000000
#define maxn 160010 

using namespace std;

int ch[maxn][2],fa[maxn],size[maxn],w[maxn];
int pos[maxn];
int tot,n,m,T,root;
char s[110];

int dir(int x)
{
	return x==ch[fa[x]][1];
}

void update(int x)
{
	size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
}

void rotate(int x)
{
	int y,z,a,b,c;
	y=fa[x];z=fa[y];b=dir(x);a=ch[x][!b];
	if (z==0) root=x;
	else
	{
		c=dir(y);ch[z][c]=x;
	}
	fa[x]=z;fa[y]=x;ch[x][!b]=y;ch[y][b]=a;
	if (a) fa[a]=y;
	update(y);update(x);
}

void splay(int x,int i)
{
	int y,z,b,c;
	while (fa[x]!=i)
	{
		y=fa[x];z=fa[y];
		if (z==i) rotate(x);
		else
		{
			b=dir(x);c=dir(y);
			if (b^c)
			{
				rotate(x);rotate(x);
			}
			else
			{
				rotate(y);rotate(x);
			}
		}
	}
}

int find_pre(int x,int d)
{
	if (!x) return x;
	if (w[x]>=d) return find_pre(ch[x][0],d);
	else
	{
		int y=find_pre(ch[x][1],d);
		if (y) return y;
		else return x;
	}
}

int find_k(int x,int k)
{
	if (size[ch[x][0]]==k-1) return x;
	if (size[ch[x][0]]>k-1) return find_k(ch[x][0],k);
	else return find_k(ch[x][1],k-size[ch[x][0]]-1);
}

void insert(int k,int d)
{
	int x=find_k(root,k);splay(x,0);
	int y=find_k(ch[x][1],1);splay(y,x);
	tot++;
	fa[tot]=y;size[tot]=1;w[tot]=d;ch[y][0]=tot;
	pos[d]=tot;
	update(y);update(x);
}

int query(int x)
{
	splay(x,0);
	return size[ch[x][0]];
}

void del(int k)
{
	int x=find_k(root,query(k));splay(x,0);
	int y=find_k(ch[x][1],2);splay(y,x);
	size[ch[y][0]]=0;fa[ch[y][0]]=0;ch[y][0]=0;
	update(y);update(x);
}

int main()
{
	size[0]=0;
	tot=2;root=1;
	fa[1]=0;size[1]=2;w[1]=-inf;ch[1][1]=2;
	fa[2]=1;size[2]=1;w[2]=inf;
	scanf("%d%d",&n,&T);
	for (int i=1;i<=n;i++)
	{
		int x;
		scanf("%d",&x);
		insert(i,x);
	}
	while (T--)
	{
		int x,y;
		scanf("%s%d",s,&x);
		if (s[0]=='Q') printf("%d\n",w[find_k(root,x+1)]);
		if (s[0]=='A') printf("%d\n",query(pos[x])-1);
		if (s[0]=='T') del(pos[x]),insert(1,x);
		if (s[0]=='B') del(pos[x]),insert(n,x);
		if (s[0]=='I')
		{
			scanf("%d",&y);
			int num=query(pos[x]);
			del(pos[x]);
			insert(num+y,x);
		}
	}
	return 0;
}


你可能感兴趣的:(【bzoj1861】[Zjoi2006]Book 书架 splay)