[ZJOI2006]书架

[ZJOI2006]书架

题目描述

小T有一个很大的书柜。这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列。她用1到n的正整数给每本书都编了号。

小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本。由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位置。不过小T的记忆力是非常好的,所以每次放书的时候至少能够将那本书放在拿出来时的位置附近,比如说她拿的时候这本书上面有X本书,那么放回去时这本书上面就只可能有X-1、X或X+1本书。

当然也有特殊情况,比如在看书的时候突然电话响了或者有朋友来访。这时候粗心的小T会随手把书放在书柜里所有书的最上面或者最下面,然后转身离开。

久而久之,小T的书柜里的书的顺序就会越来越乱,找到特定的编号的书就变得越来越困难。于是她想请你帮她编写一个图书管理程序,处理她看书时的一些操作,以及回答她的两个提问:(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语句你应该输出一行,一个数,代表询问的答案。


咦為啥我輸入法變成繁體還回不來了

數據結構大題。

似乎有各種方法可以卡過。

我們讓splay的下標表示pos,大小關係表示位置。

對於Top和Bottom,我們把x旋到根,再把左兒子接到右兒子上或相反。

對於ins 我們把x的上(下)一個位置轉到根,再把x取下來接到對面子樹。

 

細節很多!!

註意事項:

1.修改完要一整條鏈維護。

2.刪除x時要把x的兒子接到x的父親上。

3.父子關係要成對修改。

4.沒有節點的情況

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<cmath>
  7 using namespace std;
  8 int n,m,pos[100005],rt;
  9 struct node{
 10     int ch[2],f,x,sz;
 11 }tr[100005];
 12 void wh(int k){
 13     tr[k].sz=tr[tr[k].ch[0]].sz+tr[tr[k].ch[1]].sz+1;
 14 }
 15 void print_a(int x){
 16     if(!x)return;
 17     print_a(tr[x].ch[0]);
 18     printf("%d ",x);
 19     print_a(tr[x].ch[1]);
 20 }
 21 int build(int f,int l,int r){
 22     if(l>r)return 0;
 23     int mid=l+r>>1;
 24     int k=pos[mid];
 25     tr[k].x=mid;tr[k].sz=1;
 26     tr[k].f=f;
 27     tr[k].ch[0]=build(k,l,mid-1);
 28     tr[k].ch[1]=build(k,mid+1,r);
 29     wh(k);
 30     //printf("k=%d p=%d sz=%d f=%d ls=%d rs=%d\n",k,tr[k].x,tr[k].sz,tr[k].f,tr[k].ch[0],tr[k].ch[1]);
 31     return k;
 32 }
 33 bool get(int x){
 34     return tr[tr[x].f].ch[1]==x;
 35 }
 36 void rotate(int x){
 37     int y=tr[x].f,z=tr[y].f;
 38     int wx=get(x),wy=get(y);
 39     tr[z].ch[wy]=x;tr[x].f=z;
 40     tr[y].ch[wx]=tr[x].ch[wx^1];tr[tr[x].ch[wx^1]].f=y;
 41     tr[x].ch[wx^1]=y;tr[y].f=x;
 42     wh(y);wh(x);
 43 }
 44 void splay(int x,int g){
 45     while(tr[x].f!=g){
 46         int y=tr[x].f,z=tr[y].f;
 47         if(z!=g)rotate((get(x)==get(y))?y:x);
 48         rotate(x);
 49     }
 50     if(!g)rt=x;
 51 }
 52 void Top(int x){
 53     splay(x,0);
 54     int t1=tr[rt].ch[0];
 55     int t2=tr[rt].ch[1];
 56     if(!t1)return;
 57     if(!t2){swap(tr[rt].ch[0],tr[rt].ch[1]);return;}
 58     while(tr[t2].ch[0])t2=tr[t2].ch[0];
 59     tr[rt].ch[0]=0;
 60     tr[t2].ch[0]=t1;tr[t1].f=t2;
 61     for(int i=t1;i;i=tr[i].f)wh(i);
 62 }
 63 void Bottom(int x){
 64     splay(x,0);
 65     int t1=tr[rt].ch[0];
 66     int t2=tr[rt].ch[1];
 67     if(!t2)return;
 68     if(!t1){swap(tr[rt].ch[0],tr[rt].ch[1]);return;}
 69     while(tr[t1].ch[1])t1=tr[t1].ch[1];
 70     tr[rt].ch[1]=0;
 71     tr[t1].ch[1]=t2;tr[t2].f=t1;
 72     for(int i=t2;i;i=tr[i].f)wh(i);
 73 }
 74 int kth(int x){
 75     int k=rt;
 76     //cout<<x<<' '<<k<<' '<<tr[k].sz<<endl;
 77     while(1){
 78         int ls=tr[k].ch[0];
 79         if(tr[ls].sz>=x)k=ls;
 80         else if(tr[ls].sz==x-1)return k;
 81         else x-=tr[ls].sz+1,k=tr[k].ch[1];
 82     }
 83 }
 84 
 85 int find(int x){
 86     splay(x,0);
 87     return tr[tr[rt].ch[0]].sz+1;
 88 }
 89 void Ins(int x,int y){
 90     if(!y)return;
 91     int p=kth(find(x)+y);splay(p,0);
 92     if(y>0){
 93     //    cout<<rt<<endl;
 94         int wx=get(x);
 95         tr[tr[x].f].ch[wx]=tr[x].ch[wx];tr[tr[x].ch[wx]].f=tr[x].f;
 96         tr[x].ch[wx]=0;
 97         for(int i=tr[x].f;i;i=tr[i].f)wh(i);
 98         int t=tr[rt].ch[1];
 99         
100         //print_a(rt);puts("");
101         if(!t){
102             tr[rt].ch[1]=x;tr[x].f=rt;
103             wh(x);wh(rt);
104         }
105         else{
106             while(tr[t].ch[0])t=tr[t].ch[0];
107             tr[t].ch[0]=x;tr[x].f=t;
108             for(int i=x;i;i=tr[i].f)wh(i);
109         }
110     }
111     else {
112         //cout<<rt<<endl;
113         int wx=get(x);
114         tr[tr[x].f].ch[wx]=tr[x].ch[wx];tr[tr[x].ch[wx]].f=tr[x].f;
115         tr[x].ch[wx]=0;
116         for(int i=tr[x].f;i;i=tr[i].f)wh(i);
117         //print_a(rt);puts("");
118         int t=tr[rt].ch[0];
119         if(!t){
120             tr[rt].ch[0]=x;tr[x].f=rt;
121             wh(x);wh(rt);
122         }
123         else{
124             while(tr[t].ch[1])t=tr[t].ch[1];
125             tr[t].ch[1]=x;tr[x].f=t;
126             for(int i=x;i;i=tr[i].f)wh(i);
127             //print_a(rt);puts("");
128         }
129     }
130 }
131 void ask(int x){
132     int k=find(x);
133     printf("%d\n",k-1);
134 }
135 void query(int x){
136      int t=kth(x);
137     //print_a(rt);puts("");
138      printf("%d\n",t);
139 }
140 int main(){
141     cin>>n>>m;
142     for(int i=1;i<=n;i++)scanf("%d",&pos[i]);
143     rt=build(0,1,n);
144     while(m--){
145         char ch[8];int x,y;
146         scanf("%s %d",ch,&x);
147         if(ch[0]=='T')Top(x);
148         if(ch[0]=='B')Bottom(x);
149         if(ch[0]=='I'){
150             scanf("%d",&y);
151             Ins(x,y);
152         }
153         if(ch[0]=='A')ask(x);
154         if(ch[0]=='Q')query(x);
155     }
156     return 0;
157 }
View Code

 

posted @ 2019-02-18 10:32  liankewei123456  阅读(251)  评论(0编辑  收藏  举报