首页 > 代码库 > BZOJ 1861 [Zjoi2006]Book 书架 ——Splay

BZOJ 1861 [Zjoi2006]Book 书架 ——Splay

【题目分析】

    模板题目。

    首尾两个虚拟结点,十分方便操作。

【代码】

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>

#include <map>
#include <set>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>

using namespace std;

#define maxn 500005
#define inf 0x3f3f3f3f
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define L ch[o][0]
#define R ch[o][1] 

void Finout()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    #endif
}

int Getint()
{
    int x=0,f=1; char ch=getchar();
    while (ch<‘0‘||ch>‘9‘) {if (ch==‘-‘) f=-1; ch=getchar();}
    while (ch>=‘0‘&&ch<=‘9‘) {x=x*10+ch-‘0‘; ch=getchar();}
    return x*f;
}

int n,m;

struct Bit_Tree{
	int a[maxn],b[maxn];
	void add(int x,int y,int z)
	{
		for (int i=x;i<=n;i+=i&(-i)) b[i]+=z;
		for (int i=y+1;i<=n;i+=i&(-i)) b[i]-=z;
		for (int i=x;i<=n;i+=i&(-i)) a[i]+=(n-x)*z;
		for (int i=y+1;i<=n;i+=i&(-i)) a[i]-=(n-y-1)*z;
	}
	int getsum(int x)
	{
		int ret=0,tmp=0;
		for (int i=x;i;i-=i&(-i)) ret+=a[i];
		for (int i=x;i;i-=i&(-i)) tmp+=b[i];
		return ret-(n-x-1)*tmp;
	}
	void init()
	{
		memset(a,0,sizeof a);
		memset(b,0,sizeof b);
	}
}t;

int rt=0,a[maxn],s,T,id[maxn],cnt=0;
char opt[10];
int num[maxn],ch[maxn][2],siz[maxn],fa[maxn],list[maxn];

void update(int o)
{
	siz[o]=siz[L]+siz[R]+1;
}

void rot(int x,int &k)
{
//	cout<<"rot"<<x<<endl;
    int y=fa[x],z=fa[y],l,r;
    if (ch[y][0]==x) l=0; else l=1;
    r=l^1;
    if (y==k) k=x;
    else
    {
        if (ch[z][0]==y) ch[z][0]=x;
        else ch[z][1]=x;
    }
    fa[x]=z;
    fa[y]=x;
    fa[ch[x][r]]=y;
    ch[y][l]=ch[x][r];
    ch[x][r]=y;
    update(y); update(x); 
}

void splay(int x,int &k)
{
    int y,z;
    while (x!=k)
    {
        y=fa[x];z=fa[y];
        if (y!=k)
        {
            if ((ch[z][0]==y)^(ch[y][0]==x)) rot(x,k);
            else rot(y,k);
        }
        rot(x,k);
    }
}

void ins(int & o,int x,int lst)
{
	if (!o)
	{
		o=++cnt;
		fa[o]=lst;
		num[o]=x;
		siz[o]=1;
		list[o]=a[x-1];
		splay(o,rt);
		return ;
	}
	if (x<num[o]) ins(ch[o][0],x,o);
	else ins(ch[o][1],x,o);
	update(o);
}

int find(int o,int x)
{
//	cout<<"qnum"<<num[o]<<" "<<x<<endl; 
	if (siz[L]+1==x) return o;
	if (siz[L]>=x) return find(L,x);
	else return find(R,x-siz[L]-1);
}

void print(int o)
{
	if (!o) return ;
	print(L);
//	cout<<"now is "<<o<<endl;
//	cout<<L<<" "<<R<<endl;
//	cout<<num[o]<<" "<<siz[o]<<endl;
	cout<<num[o]<<" ";
	print(R);
}


void Mov(int o,int k)
{
	splay(o,rt);
	int pre=find(rt,siz[L]),nxt=find(rt,siz[L]+2);
	splay(pre,rt); splay(nxt,ch[rt][1]);
	ch[nxt][0]=0; fa[o]=0;
	update(nxt); update(pre);
	splay(nxt,rt);
	pre=find(rt,k-1);nxt=find(rt,k);
	splay(pre,rt); splay(nxt,ch[rt][1]);
	ch[nxt][0]=o; fa[o]=nxt;
	splay(o,rt);
}

int main()
{
    Finout();
    scanf("%d%d",&n,&m);
    F(i,1,n) scanf("%d",&a[i]),id[a[i]]=i+1;
    F(i,0,n+1) ins(rt,i,0);
//    print(rt);
//    cout<<rt<<endl;
    F(i,1,m)
    {
//    	print(rt);
//    	cout<<endl;
    	scanf("%s",opt);
    	scanf("%d",&s);
    	if (opt[0]==‘Q‘)
		{
//			cout<<"QUERY"<<endl;
			printf("%d\n",a[find(rt,s+1)-1]);
		}
    	else if (opt[0]==‘A‘)
    	{
//    		cout<<"ASK"<<endl;
    		splay(id[s],rt);
    		printf("%d\n",siz[ch[rt][0]]-1);
		}
		else if (opt[0]==‘T‘)
		{
//			cout<<"TOP"<<endl;
			Mov(id[s],1+1);
		}
		else if (opt[0]==‘B‘)
		{
//			cout<<"BOT"<<endl;
			Mov(id[s],n+1);
		}
		else
		{
			T=Getint();
			splay(id[s],rt);
			int tmp=siz[ch[rt][0]];
			Mov(id[s],tmp+T+1);
		}
	}
}

  

BZOJ 1861 [Zjoi2006]Book 书架 ——Splay