[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\n",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\n",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 }