基础平衡树操作,del+insert
这道题就是还要记录一下平衡树中的编号和对应的书的编号,注意这两个都不是单调的
写平衡树的时候,老是脑子有病。。总觉得平衡树里的标号是单调的。。
这个也是模板没有修改前写的,常数较大。。。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int read(){ 4 int x=0,f=1;char ch=getchar(); 5 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 6 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 7 return x*f; 8 } 9 #define N 80005 10 int n,m,a[N],pos[N],root,sz[N],ch[N][2],fa[N]; 11 void pushup(int x){ 12 sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1; 13 } 14 void build(int l,int r,int f){ 15 int mid=l+r>>1; 16 sz[mid]=1;fa[mid]=f; 17 if(mid<f)ch[f][0]=mid;else ch[f][1]=mid; 18 if(l==r)return; 19 if(l<mid)build(l,mid-1,mid); 20 if(r>mid)build(mid+1,r,mid); 21 pushup(mid); 22 } 23 void rotate(int x,int &beto){ 24 int y=fa[x],t=ch[y][1]==x; 25 if(y!=beto)ch[fa[y]][ch[fa[y]][1]==y]=x;else beto=x; 26 fa[x]=fa[y];fa[y]=x; 27 fa[ch[x][!t]]=y; 28 ch[y][t]=ch[x][!t]; 29 ch[x][!t]=y; 30 pushup(y);pushup(x); 31 } 32 void splay(int x,int &beto){ 33 while(x!=beto){ 34 int y=fa[x]; 35 if(y!=beto){ 36 if((ch[fa[y]][1]==y)==(ch[y][1]==x))rotate(y,beto); 37 else rotate(x,beto); 38 }rotate(x,beto); 39 } 40 } 41 int find_k(int x,int k){ 42 if(sz[ch[x][0]]==k-1)return x; 43 if(sz[ch[x][0]]<k-1)return find_k(ch[x][1],k-sz[ch[x][0]]-1); 44 return find_k(ch[x][0],k); 45 } 46 void del(int x){ 47 int l=find_k(root,x-1),r=find_k(root,x+1); 48 splay(l,root);splay(r,ch[l][1]); 49 x=ch[r][0];ch[r][0]=0; 50 pushup(r);pushup(l); 51 } 52 int main(){ 53 n=read();m=read();n+=2; 54 for(int i=2;i<n;i++)a[i]=read(),pos[a[i]]=i; 55 build(1,n,0);root=(1+n)>>1; 56 char s[10];int x; 57 for(int i=1;i<=m;i++){ 58 scanf("%s",s);x=read(); 59 if(s[0]=='T'){ 60 int p=pos[x],rk; 61 splay(p,root);rk=sz[ch[p][0]]+1; 62 del(rk); 63 int l=find_k(root,1),r=find_k(root,2); 64 splay(l,root);splay(r,ch[l][1]); 65 ch[r][0]=p;fa[p]=r; 66 pushup(r);pushup(l); 67 } 68 else if(s[0]=='B'){ 69 int p=pos[x],rk; 70 splay(p,root);rk=sz[ch[p][0]]+1; 71 del(rk); 72 int l=find_k(root,n-2),r=find_k(root,n-1); 73 splay(l,root);splay(r,ch[l][1]); 74 ch[r][0]=p;fa[p]=r; 75 pushup(r);pushup(l); 76 } 77 else if(s[0]=='I'){ 78 int t=read(); 79 int p=pos[x],rk; 80 splay(p,root);rk=sz[ch[p][0]]+1; 81 del(rk); 82 int l=find_k(root,rk+t-1),r=find_k(root,rk+t); 83 splay(l,root);splay(r,ch[l][1]); 84 ch[r][0]=p;fa[p]=r; 85 pushup(r);pushup(l); 86 } 87 else if(s[0]=='A'){ 88 int p=pos[x],rk; 89 // cout<<"p "<<p<<endl; 90 splay(p,root);rk=sz[ch[p][0]]+1; 91 // cout<<"rk "<<rk<<endl; 92 printf("%d\n",rk-2); 93 } 94 else if(s[0]=='Q'){ 95 int p=find_k(root,x+1); 96 printf("%d\n",a[p]); 97 } 98 } 99 return 0; 100 }
1861: [Zjoi2006]Book 书架
Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 1183 Solved: 689
[Submit][Status][Discuss]
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
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
9
9
7
5
3
HINT
数据范围