BZOJ 1861 Book 書架 第一份完全憑自己理解手敲的Splay樹啊。記念一下
阿新 • • 發佈:2019-02-01
// // 1861.cpp // ACM_BZOJ // // Created by ipqhjjybj on 13-9-9. // Copyright (c) 2013年 ipqhjjybj. All rights reserved. // 第一道完全手敲得啊。任重道遠。。 // #include <cstdio> #include <cstdlib> #include <map> #include <cstring> using namespace std; #define Key_Tree child[child[root][1]][0] int n; struct SplayTree{ const static int maxn=111111; int n,tot,root; int pre[maxn],size[maxn];//flex[maxn] int child[maxn][2]; int a[maxn]; void Travel(int u){ if(!u) return; printf("u=%d c0=%d c1=%d s0=%d s1=%d\n",u,child[u][0],child[u][1],size[child[u][0]]+size[child[u][1]]); Travel(child[u][0]); Travel(child[u][1]); } void Push_up(int &x){ size[x]=size[child[x][0]]+size[child[x][1]]+1; } void Del_root(){ int t=root; if(child[root][1]){ root=child[root][1]; // printf("root=%d\n",root); Select(1,0); child[root][0]=child[t][0]; if(child[t][0]) pre[child[t][0]]=root; }else root=child[root][0]; pre[root]=0; Push_up(root); child[t][0]=child[t][1]=0;//清空t size[t]=1; } //c==0 左旋 c==1 右旋 inline void Rotate(int x,int c){ int y=pre[x]; //Pushdown(y),Pushdown(x); child[y][!c]=child[x][c]; if(child[x][c]) pre[child[x][c]]=y; pre[x]=pre[y]; if(pre[y]) child[pre[y]][child[pre[y]][1]==y]=x; child[x][c]=y; pre[y]=x; Push_up(y); } void Splay(int x,int f){ //Push_down(x); while(pre[x]!=f){ int y=pre[x],z=pre[y]; //Push_down(z),Push_down(y),Push_down(x); if(pre[pre[x]]==f){ Rotate(x,child[pre[x]][0]==x); }else{ if(child[z][0]==y){ if(child[y][0]==x) Rotate(y,1),Rotate(x,1); else Rotate(x,0),Rotate(x,1); }else{ if(child[y][0]==x) Rotate(x,1),Rotate(x,0); else Rotate(y,0),Rotate(x,0); } } } Push_up(x); if(!f) root=x; } int Select(int k,int f){ int x=root; while(1){ if(k==size[child[x][0]]+1) break; if(k<=size[child[x][0]]) x=child[x][0]; else{ k-=size[child[x][0]]+1; x=child[x][1]; } } Splay(x,f); return x; } //after one number's void Insert(int t,int after){ Select(after,0); int x=Select(after+1,root); Key_Tree=t;//或者child[x][0]=t; pre[t]=x; Push_up(t); Push_up(x); } void Top(int t){ Select(1,0); child[root][0]=t; pre[t]=root; Push_up(t); Push_up(root); } int Find_kth(int k){ int t=root; while(1){ if(size[child[t][0]]+1==k) break; else if(size[child[t][0]]>=k) t=child[t][0]; else k-=size[child[t][0]]+1,t=child[t][1]; } return t; } void Init(int _n){ n=_n; for(int i=1;i<=n;i++) scanf("%d",a+i); memset(child,0,(n+3)*2*sizeof(int)); for(int i=1;i<=n;i++){ pre[i-1]=i; child[i][0]=i-1; size[i]=i; }pre[n]=n+1,child[n+1][0]=n,a[n+1]=n+1,pre[n+1]=0,root=n+1,a[0]=0; size[0]=0,size[n+1]=n+1; child[0][0]=child[0][1]=0; Map.clear(); for(int i=1;i<=n;i++) Map[a[i]]=i; } map<int,int> Map; }spt; void Init(int n){ spt.Init(n); } int Ask(int t){ spt.Splay(t,0); return spt.size[spt.child[t][0]]; } void Top(int t){ spt.Splay(t,0); spt.Del_root(); spt.Top(t); } int Query(int k){ return spt.a[spt.Find_kth(k)]; } void Bottom(int t){ spt.Splay(t,0); spt.Del_root(); spt.Insert(t,n-1); } void Insert(int t,int val){ spt.Splay(t,0); int sz=spt.size[spt.child[t][0]]; sz+=val; if(sz==0){ //個人的函式問題,需要特判 Top(t); return; }else if(sz==n-1){ Bottom(t); return; } spt.Del_root(); spt.Insert(t,sz); } void Solve(int m){ char str[10]; int val,num; while(m--){ scanf("%s",str); if(str[0]=='Q'){//query scanf("%d",&val); printf("%d\n",Query(val)); }else if(str[0]=='T'){//top scanf("%d",&val); Top(spt.Map[val]); }else if(str[0]=='A'){//ask scanf("%d",&val); printf("%d\n",Ask(spt.Map[val])); }else if(str[0]=='B'){//bottom scanf("%d",&val); Bottom(spt.Map[val]); }else if(str[0]=='I'){//insert scanf("%d %d",&val,&num); if(num!=0) Insert(spt.Map[val],num); } } } int main(){ int m; scanf("%d %d",&n,&m); Init(n); Solve(m); return 0; }