Description
Sally有一個很大的書櫃。這個書櫃的構造有些獨特,即書櫃裏的書是從上至下堆放成一列。她用1到n的正整數給每本書都編了號。Sally在看書的時候,每次取出一本書,看完後放回書櫃而後再拿下一本。因爲這些書太有吸引力了,因此她看完後經常會忘記原來是放在書櫃的什麼位置。不過Sally的記憶力是很是好的,因此每次放書的時候至少可以那本書放在拿出來時的位置附近,好比說她拿的時候這本書上面有X本書,那麼放回去時這本書上面就只可能有X-一、X或X+1本書。固然也有特殊狀況,好比在看書的時候忽然電話響了或者有朋友來訪。這時候粗心的Sally會隨手把書放在書櫃裏全部書的最上面或者最下面,而後轉身離開。長此以往,Sally的書櫃裏的書的順序就會愈來愈亂,找到特定的編號的書就變得愈來愈困難。因而她想請你幫她編寫一個圖書管理程序,處理她看書時的一些操做,以及回答她的兩個提問:(1)編號爲X的書在書櫃的什麼位置;(2)從上到下第i本書的編號是多少。html
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本書的編號。
n,m<=80000ios
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 2ui
Sample Output
2
9
9
7
5
3spa
這題多兩個操做,取出最靠右的點和最靠左的點。insert操做把點往左挪或往右挪,Top/Down放到最上面或最下面就行了,具體操做能夠看下代碼code
關於本人splay代碼操做詳解請參考淺談算法——splayhtm
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define inf 0x7f7f7f7f using namespace std; typedef long long ll; typedef unsigned int ui; typedef unsigned long long ull; inline int read(){ int x=0,f=1;char ch=getchar(); for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1; for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+ch-'0'; return x*f; } inline void print(int x){ if (x>=10) print(x/10); putchar(x%10+'0'); } const int N=8e4; struct Splay{ #define T(x) (tree[f[x]][1]==x) int tree[N+10][2],f[N+10],size[N+10],val[N+10]; int root,len; void updata(int x){size[x]=size[tree[x][0]]+size[tree[x][1]]+1;} void build(int n){ for (int i=1;i<=n;i++) val[i]=read(); for (int i=1;i<n;i++) f[val[i]]=val[i+1],tree[val[i+1]][0]=val[i],size[val[i]]=i; size[root=val[n]]=n; } void move(int x){ int fa=f[x],son=tree[x][T(x)^1]; tree[x][T(x)^1]=fa; tree[fa][T(x)]=son; if (son) f[son]=fa; f[x]=f[fa]; if (f[x]) tree[f[x]][T(fa)]=x; f[fa]=x; updata(fa),updata(x); } void splay(int x){ while (f[x]){ if (f[f[x]]) T(x)==T(f[x])?move(f[x]):move(x); move(x); } root=x; } int get_pre(){ int x=tree[root][0]; while (tree[x][1]) x=tree[x][1]; return x; } int get_suc(){ int x=tree[root][1]; while (tree[x][0]) x=tree[x][0]; return x; } int get_front(){ int x=root; while (tree[x][0]) x=tree[x][0]; return x; } int get_last(){ int x=root; while (tree[x][1]) x=tree[x][1]; return x; } void Delete(int x){ splay(x); if (!(tree[x][0]&&tree[x][1])){ f[root=tree[x][0]+tree[x][1]]=0; f[x]=tree[x][0]=tree[x][1]=size[x]=0; return; } int i=get_pre(); splay(i); f[tree[i][1]=tree[x][1]]=i; f[x]=tree[x][0]=tree[x][1]=size[x]=0; updata(i); } int find(int x,int i){ if (size[tree[i][0]]+1==x) return i; if (x<=size[tree[i][0]]) return find(x,tree[i][0]); return find(x-size[tree[i][0]]-1,tree[i][1]); } void change(int x,int t){ Delete(x); int i=t?get_last():get_front(); splay(i); f[tree[i][t]=x]=i; size[x]++,size[i]++; } void insert(int x,int t){ splay(x); int i=t?get_suc():get_pre(); Delete(x); splay(i); f[tree[x][t]=tree[i][t]]=x; f[tree[i][t]=x]=i; size[x]=size[tree[x][t]]+1; size[i]++; } void Ask(int x){ splay(x); printf("%d\n",size[tree[x][0]]); } void query(int x){printf("%d\n",find(x,root));} }T; char s[10]; int main(){ int n=read(),m=read(); T.build(n); for (int i=1;i<=m;i++){ scanf("%s",s); if (s[0]=='I'){ int x=read(),t=read(); if (t) T.insert(x,t==1); } if (s[0]=='T') T.change(read(),0); if (s[0]=='B') T.change(read(),1); if (s[0]=='A') T.Ask(read()); if (s[0]=='Q') T.query(read()); } return 0; }