[LSGDOJ1822]书架 Splay

题目描述

Sally有一个很大的书柜。这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列。她用1到n的正整数给每本书都编了号。
Sally在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本。由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位置。不过Sally的记忆力是非常好的,所以每次放书的时候至少能够那本书放在拿出来时的位置附近,比如说她拿的时候这本书上面有X本书,那么放回去时这本书上面就只可能有X-1、X或X+1本书。
    当然也有特殊情况,比如在看书的时候突然电话响了或者有朋友来访。这时候粗心的Sally会随手把书放在书柜里所有书的最上面或者最下面,然后转身离开。
    久而久之,Sally的书柜里的书的顺序就会越来越乱,找到特定的编号的书就变得越来越困难。于是她想请你帮她编写一个图书管理程序,处理她看书时的一些操作,以及回答她的两个提问:(1)编号为X的书在书柜的什么位置;(2)从上到下第i本书的编号是多少。

输入

第一行有两个数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本书的编号。

输出

对于每一条Ask或Query语句你应该输出一行,一个数,代表询问的答案。

样例输入

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

样例输出

2 9 9 7 5 3

提示

 30%的数据,n,m<=10000

100%的数据,n,m<=80000
 
题解:
关键是开一个*id[i]保存编号为i的书所在节点的编号,然后在newnode的时候更新他的位置
题目中
Insert就是交换id[x]和他的前驱的id的值,然后再换节点对应的编号.
Bottom就是删掉该节点,在把它的位置改成maxn+1(使得他的编号比任何一个节点都大,就达到了放在底端的效果),maxn表示当前最大的编号,并把maxn++.Top同理
Query就是把x转到根,然后答案就是左子节点的size
Ask 就是排名为k的数
然后就开始乱搞
我犯的低级错误:
1.insert y=0时没特判
2.把第一个数放在顶端也没特判
代码如下:
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cmath>
  6 #include<cstdlib>
  7 #include<ctime>
  8 using namespace std;
  9 const int N=80005,INF=1999999999;
 10 struct node
 11 {
 12     int x,size,book;
 13     node *child[2],*fa;
 14 }a[N*4];
 15 node *pos=a,*root,*id[N];
 16 void newnode(node *&r,int key,node *ff,int number)
 17 {
 18     r=pos++;
 19     r->size=1,id[number]=r;
 20     r->x=key;r->fa=ff;r->book=number;
 21     r->child[0]=r->child[1]=NULL;
 22 }
 23 int gi()
 24 {
 25     int str=0;char ch=getchar();
 26     while(ch>'9' || ch<'0')ch=getchar();
 27     while(ch>='0'&& ch<='9')str=str*10+ch-'0',ch=getchar();
 28     return str;
 29 }
 30 int n,m;
 31 void updata(node *&r)
 32 {
 33     if(r){
 34         r->size=(r->child[0]?r->child[0]->size:0)+(r->child[1]?r->child[1]->size:0)+1;
 35         return ;
 36     }
 37 }
 38 void rotate(node *&r,bool t)
 39 {
 40     node *y=r->fa;
 41     y->child[!t]=r->child[t];
 42     if(r->child[t])r->child[t]->fa=y;
 43     r->fa=y->fa;
 44     if(y->fa)y->fa->child[y->fa->child[1]==y]=r;
 45     r->child[t]=y;
 46     y->fa=r;
 47     updata(y);
 48     updata(r);
 49     updata(r->fa);
 50 }
 51 void splay(node *r,node *g)
 52 {
 53     while(r->fa!=g)
 54     {
 55         if(r->fa->fa==g)rotate(r,r->fa->child[0]==r);
 56         else{
 57             node *y=r->fa;
 58             bool t=y->fa->child[0]==y;
 59             if(y->child[t]==r)rotate(r,!t);
 60             else rotate(y,t);
 61             rotate(r,t);
 62         }
 63     }
 64     if(g==NULL)root=r;
 65 }
 66 void insert(node *&r,int key,node *fa,int number)
 67 {
 68     if(r==NULL){
 69         newnode(r,key,fa,number);
 70         splay(r,NULL);
 71         return;
 72     }
 73     else insert(r->child[key>r->x],key,r,number);
 74 }
 75 node *pre,*nxt;
 76 char s[12];
 77 void getpre(node *r,int key)
 78 {
 79     if(!r)return ;
 80     if(r->x>=key)getpre(r->child[0],key);
 81     else pre=r,getpre(r->child[1],key);
 82 }
 83 void getnext(node *r,int key)
 84 {
 85     if(!r)return ;
 86     if(r->x<=key)getnext(r->child[1],key);
 87     else nxt=r,getnext(r->child[0],key);
 88 }
 89 void Ask(int x)
 90 {
 91     splay(id[x],NULL);
 92     printf("%d
",root->child[0]?root->child[0]->size:0);
 93     return ;
 94 }
 95 int getrank(node *r,int rk)
 96 {
 97     while(r){
 98         int d=r->child[0]?r->child[0]->size:0;
 99         if(rk==d+1)return r->book;
100         if(rk<d+1)r=r->child[0];
101         else rk-=d+1,r=r->child[1];
102     }
103     return -1;
104 }
105 node *findmax(node *r)
106 {
107     if(r->child[1])return findmax(r->child[1]);
108     else return r;
109 }
110 int maxn=1,minn=1;
111 void Delet(int x)
112 {
113     node *y;
114     splay(id[x],NULL);
115     if(root->child[0]){
116         y=findmax(root->child[0]);
117         splay(y,root);      
118         y->child[1]=root->child[1];
119         y->fa=NULL;
120         if(root->child[1])
121         root->child[1]->fa=y;
122         root=y;
123         updata(y);
124     }
125     else{
126         root=root->child[1];
127         root->fa=NULL;
128     }
129 }
130 void Totop(int x,bool t)
131 {
132     Delet(x);
133     if(!t)
134     insert(root,--minn,NULL,x);
135     else
136     insert(root,++maxn,NULL,x);
137 }
138 void change(int x,int y)
139 {
140     node *kl;
141     if(y==1)getnext(root,id[x]->x),kl=nxt;
142     else getpre(root,id[x]->x),kl=pre;
143     y=kl->book;
144     swap(id[x],id[y]);
145     swap(id[x]->book,id[y]->book);
146 }
147 int main()
148 {
149     int x,y;
150     n=gi();m=gi();maxn=n;
151     for(int i=1;i<=n;i++){
152         x=gi();
153         insert(root,i,NULL,x);
154     }
155     int cc=0;
156     while(m--){
157         scanf("%s%d",s,&x);
158         if(s[0]=='A')Ask(x);
159         else if(s[0]=='Q')printf("%d
",getrank(root,x));
160         else if(s[0]=='I'){scanf("%d",&y);if(y)change(x,y);}
161         else if(s[0]=='T')Totop(x,0);
162         else if(s[0]=='B')Totop(x,1);
163     }
164     return 0;
165 }
原文地址:https://www.cnblogs.com/Yuzao/p/6816915.html