• [BZOJ1861][ZJOI2006]书架


    BZOJ
    Luogu
    Description
    小T有一个很大的书柜。这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列。她用1到n的正整数给每本书都编了号。 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本。由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位置。不过小T的记忆力是非常好的,所以每次放书的时候至少能够将那本书放在拿出来时的位置附近,比如说她拿的时候这本书上面有X本书,那么放回去时这本书上面就只可能有X-1、X或X+1本书。 当然也有特殊情况,比如在看书的时候突然电话响了或者有朋友来访。这时候粗心的小T会随手把书放在书柜里所有书的最上面或者最下面,然后转身离开。 久而久之,小T的书柜里的书的顺序就会越来越乱,找到特定的编号的书就变得越来越困难。于是她想请你帮她编写一个图书管理程序,处理她看书时的一些操作,以及回答她的两个提问:(1)编号为X的书在书柜的什么位置;(2)从上到下第i本书的编号是多少。
    Input
    第一行有两个数n,m,分别表示书的个数以及命令的条数;第二行为n个正整数:第i个数表示初始时从上至下第i个位置放置的书的编号;第三行到m+2行,每行一条命令。命令有5种形式: 1. Top S——表示把编号为S的书房在最上面。 2. Bottom S——表示把编号为S的书房在最下面。 3. Insert S T——T∈{-1,0,1},若编号为S的书上面有X本书,则这条命令表示把这本书放回去后它的上面有X+T本书; 4. Ask S——询问编号为S的书的上面目前有多少本书。 5. Query S——询问从上面数起的第S本书的编号。
    Output
    对于每一条Ask或Query语句你应该输出一行,一个数,代表询问的答案。
    Sample Input

    10 10 
    1 3 2 7 5 8 10 4 9 6
    Query 3 
    Top 5 
    Ask 6 
    Bottom 3 
    Ask 3 
    Top 6 
    Insert 4 -1 
    Query 5 
    Query 2 
    Ask 2 
    

    Sample Output

    2
    9
    9
    7
    5
    3
    

    HINT
    100%的数据,n,m < = 80000

    sol

    就是splay板子题呀(然而还是调了我将近两个小时)
    操作1,2注意判本来就是Top或是Bottom的情况
    操作3注意交换splay树上的两个节点的时候会涉及很多东西的变动,最好画个图仔细想一想,然后要PUSHUP!(我就是这里WA的)
    操作4,5应该是最简单的,就不讲了
    练细节的好题吧

    code

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N = 100005;
    int n,m,fa[N],ls[N],rs[N],sz[N],a[N],root;
    char s[N];
    int gi()
    {
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    void pushup(int x){sz[x]=sz[ls[x]]+sz[rs[x]]+1;}
    void R_rotate(int x)
    {
    	int y=fa[x],z=fa[y];
    	ls[y]=rs[x];
    	if (rs[x]) fa[rs[x]]=y;
    	fa[x]=z;
    	if (z) if (y==ls[z]) ls[z]=x;else rs[z]=x;
    	rs[x]=y;fa[y]=x;
    	pushup(y);
    }
    void L_rotate(int x)
    {
    	int y=fa[x],z=fa[y];
    	rs[y]=ls[x];
    	if (ls[x]) fa[ls[x]]=y;
    	fa[x]=z;
    	if (z) if (y==ls[z]) ls[z]=x;else rs[z]=x;
    	ls[x]=y;fa[y]=x;
    	pushup(y);
    }
    void splay(int x,int goal)
    {
    	while (fa[x]!=goal)
    	{
    		int y=fa[x],z=fa[y];
    		if (z==goal)
    			if (x==ls[y]) R_rotate(x);
    			else L_rotate(x);
    		else
    			if (y==ls[z])
    				if (x==ls[y]) R_rotate(y),R_rotate(x);
    				else L_rotate(x),R_rotate(x);
    			else
    				if (x==ls[y]) R_rotate(x),L_rotate(x);
    				else L_rotate(y),L_rotate(x);
    	}
    	pushup(x);
    	if (!goal) root=x;
    }
    void Top()
    {
    	int x=gi();
    	splay(x,0);
    	if (!ls[x]) return;
    	int y=ls[x];
    	while (rs[y]) y=rs[y];
    	splay(y,x);
    	rs[y]=rs[x];if (rs[y]) fa[rs[y]]=y;
    	fa[root=y]=0;pushup(y);
    	while (ls[y]) y=ls[y];
    	ls[y]=x;fa[x]=y;ls[x]=rs[x]=0;sz[x]=1;
    	splay(x,0);
    }
    void Bottom()
    {
    	int x=gi();
    	splay(x,0);
    	if (!rs[x]) return;
    	int y=rs[x];
    	while (ls[y]) y=ls[y];
    	splay(y,x);
    	ls[y]=ls[x];if (ls[y]) fa[ls[y]]=y;
    	fa[root=y]=0;pushup(y);
    	while (rs[y]) y=rs[y];
    	rs[y]=x;fa[x]=y;ls[x]=rs[x]=0;sz[x]=1;
    	splay(x,0);
    }
    void Insert()
    {
    	int x=gi(),t=gi();
    	splay(x,0);
    	if (t==1)
    	{
    		int y=rs[x];
    		while (ls[y]) y=ls[y];
    		splay(y,x);
    		swap(ls[x],ls[y]);if (ls[x]) fa[ls[x]]=x;if (ls[y]) fa[ls[y]]=y;
    		rs[x]=rs[y];if (rs[x]) fa[rs[x]]=x;
    		rs[y]=x;fa[x]=y;
    		fa[root=y]=0;
    		pushup(x);pushup(y);
    	}
    	if (t==-1)
    	{
    		int y=ls[x];
    		while (rs[y]) y=rs[y];
    		splay(y,x);
    		swap(rs[x],rs[y]);if (rs[x]) fa[rs[x]]=x;if (rs[y]) fa[rs[y]]=y;
    		ls[x]=ls[y];if (ls[x]) fa[ls[x]]=x;
    		ls[y]=x;fa[x]=y;
    		fa[root=y]=0;
    		pushup(x);pushup(y);
    	}
    }
    void Ask()
    {
    	int x=gi();
    	splay(x,0);
    	printf("%d
    ",sz[ls[x]]);
    }
    void Query()
    {
    	int k=gi(),x=root;
    	while (233)
    	{
    		if (k<=sz[ls[x]]) x=ls[x];
    		else if (k==sz[ls[x]]+1) break;
    		else k-=sz[ls[x]]+1,x=rs[x];
    	}
    	printf("%d
    ",x);
    }
    int Build(int l,int r,int ff)
    {
    	if (l>r) return 0;
    	int mid=l+r>>1;
    	fa[a[mid]]=ff;
    	ls[a[mid]]=Build(l,mid-1,a[mid]);
    	rs[a[mid]]=Build(mid+1,r,a[mid]);
    	pushup(a[mid]);
    	return a[mid];
    }
    int main()
    {
    	n=gi();m=gi();
    	for (int i=1;i<=n;i++)
    		a[i]=gi();
    	root=Build(1,n,0);
    	while (m--)
    	{
    		scanf("%s",s);
    		if (s[0]=='T') Top();
    		if (s[0]=='B') Bottom();
    		if (s[0]=='I') Insert();
    		if (s[0]=='A') Ask();
    		if (s[0]=='Q') Query();
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    【MYSQL】SQL 的join 区别
    【Django】Django model与数据库操作对应关系(转)
    【Mysql】复制表结构+数据(转)
    【Django】Python web开发:几个模板系统的性能对比(转)
    【Mysql】Mysql关键字
    【Mysql】MySQL与Oracle的大小写问题
    Linux常用操作
    执行程序的两种方式
    Django框架的安装与使用
    web介绍
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8175810.html
Copyright © 2020-2023  润新知