• P2596 [ZJOI2006]书架


    题目链接

    题意分析

    明眼人一看就会发现这是一道裸的Splay吧准确来说是平衡树可是本蒟蒻就会使用Splay

    对于五种操作 转换成Splay就是

    1.把指定元素放在序列首位

    我们让该元素成为root 然后将ta的左子树合并到该元素的后继

    2.把指定元素放在序列末尾

    我们让该元素成为root 然后将ta的右子树合并到该元素的前驱

    3.把该元素向上/下移动一位

    将该元素同其前驱/后继交换

    4.查询元素k的排名

    5.查询排名为k的元素

    不过由于这里的元素存在编号 而且编号不是Splay中用于排序的权值

    所以 这里的Splay需要使用插入顺序以及后面的调整作为排序的依据

    同时使用一个数组 pos[x] 表示编号为x的元素对应在Splay的位置

    CODE:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define M 1008611
    using namespace std;
    int n,m,cnt,root;
    int pos[M];
    struct Tree
    {
    	int son[2],fa,siz,val;
    }tre[M];
    int getd(int x)
    {return tre[tre[x].fa].son[1]==x;}
    void pushup(int x)
    {
    	tre[x].siz=tre[tre[x].son[0]].siz+tre[tre[x].son[1]].siz+1;
    	pos[tre[tre[x].son[0]].val]=tre[x].son[0];
    	pos[tre[tre[x].son[1]].val]=tre[x].son[1];
    	pos[tre[x].val]=x;//时刻要注意更新编号
    }
    void rotate(int x)
    {
    	int fat=tre[x].fa,fatt=tre[tre[x].fa].fa;
    	int d1=getd(x),d2=getd(fat);
    	tre[fat].son[d1]=tre[x].son[d1^1];tre[tre[x].son[d1^1]].fa=fat;
    	tre[fatt].son[d2]=x;tre[x].fa=fatt;
    	tre[x].son[d1^1]=fat;tre[fat].fa=x;
    	pushup(fat);pushup(x);
    }
    void Splay(int x,int goal)
    {
    	while(tre[x].fa!=goal)
    	{
    		int fat=tre[x].fa,fatt=tre[tre[x].fa].fa;
    		int d1=getd(x),d2=getd(fat);
    		if(fatt!=goal)
    		{
    			if(d1==d2) rotate(fat);
    			else rotate(x);
    		}
    		rotate(x);
    	}
    	if(goal==0) root=x;
    }
    void insert(int x)
    {
    	tre[++cnt].val=x;tre[cnt].siz=1;
    	pos[x]=cnt;tre[cnt].son[0]=tre[cnt].son[1]=0;
    	if(cnt>1)
    	{
    		tre[cnt-1].son[1]=cnt;
    		tre[cnt].fa=cnt-1;
    		Splay(cnt,0);
    	}
    }
    void Top(int x)
    {
    	x=pos[x];Splay(x,0);
    	if(!tre[x].son[0]) return;
    	else if(!tre[x].son[1]) tre[x].son[1]=tre[x].son[0],tre[x].son[0]=0;
    	else
    	{
    		int now=tre[x].son[1];
    		while(tre[now].son[0]) now=tre[now].son[0];
    		tre[tre[x].son[0]].fa=now;
    		tre[now].son[0]=tre[x].son[0];
    		tre[x].son[0]=0;
    		Splay(now,0);
    	}
    }
    void Bottom(int x)
    {
    	x=pos[x];Splay(x,0);
    	if(!tre[x].son[1]) return;
    	else if(!tre[x].son[0]) tre[x].son[0]=tre[x].son[1],tre[x].son[1]=0;
    	else
    	{
    		int now=tre[x].son[0];
    		while(tre[now].son[1]) now=tre[now].son[1];
    		tre[tre[x].son[1]].fa=now;
    		tre[now].son[1]=tre[x].son[1];
    		tre[x].son[1]=0;
    		Splay(now,0);
    	}
    }
    void Change(int x,int y)
    {
    	if(y==0) return;
    	x=pos[x];
    	Splay(x,0);
    	if(y==1)
    	{
    		if(!tre[x].son[1]) return;
    		else
    		{
    			int now=tre[x].son[1];
    			while(tre[now].son[0]) now=tre[now].son[0];
    			pos[tre[x].val]=now;pos[tre[now].val]=x;
    			swap(tre[x].val,tre[now].val);
    		}
    	}
    	else
    	{
    		if(!tre[x].son[0]) return;
    		else
    		{
    			int now=tre[x].son[0];
    			while(tre[now].son[1]) now=tre[now].son[1];
    			pos[tre[x].val]=now;pos[tre[now].val]=x;
    			swap(tre[x].val,tre[now].val);
    		}
    	}
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1,x;i<=n;++i)
    	{
    		scanf("%d",&x);
    		insert(x);
    	}
    	while(m--)
    	{
    		char s[10];int x,y;
    		scanf("%s",s);
    		if(s[0]=='T')
    		{
    			scanf("%d",&x);
    			Top(x);
    		}
    		if(s[0]=='B')
    		{
    			scanf("%d",&x);
    			Bottom(x);
    		}
    		if(s[0]=='I')
    		{
    			scanf("%d%d",&x,&y);
    			Change(x,y);
    		}
    		if(s[0]=='A')
    		{
    			scanf("%d",&x);
    			x=pos[x];
    			Splay(x,0);
    			printf("%d
    ",tre[tre[x].son[0]].siz); 
    		}
    		if(s[0]=='Q')
    		{
    			scanf("%d",&x);
    			int now=root;
    			while(1)
    			{
    				if(tre[tre[now].son[0]].siz>=x) now=tre[now].son[0];
    				else if(tre[tre[now].son[0]].siz+1<x)
    				{
    					x-=tre[tre[now].son[0]].siz+1;
    					now=tre[now].son[1];
    				}
    				else break;
    			}
    			printf("%d
    ",tre[now].val);	
    		}
    	}
    	return 0;
    } 
    
  • 相关阅读:
    C# Firefox Session Manager 文件的导出与管理
    安徒生的童话《冰雪皇后》原本是这样的
    许多人不知道的生活小秘方
    洗衣服窍门大全
    小窍门解决大问题(绝对值得收藏)
    日常生活小技巧
    谷歌浏览器应用商店打不开,下载不了扩展程序的解决办法
    食品安全如何让百姓放心
    把 WORD 里的换行符(向下的箭头)换成回车符(常用回车符)
    充满创意的生活小妙招 --爱生活爱创意!
  • 原文地址:https://www.cnblogs.com/LovToLZX/p/14325733.html
Copyright © 2020-2023  润新知