bzoj3224 普通平衡樹 splay模板題
阿新 • • 發佈:2019-02-19
題目連結:戳這裡
3224: Tyvj 1728 普通平衡樹
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 17768 Solved: 7799
[Submit][Status][Discuss]
Description
您需要寫一種資料結構(可參考題目標題),來維護一些數,其中需要提供以下操作:
1. 插入x數
2. 刪除x數(若有多個相同的數,因只刪除一個)
3. 查詢x數的排名(若有多個相同的數,因輸出最小的排名)
4. 查詢排名為x的數
5. 求x的前驅(前驅定義為小於x,且最大的數)
6. 求x的後繼(後繼定義為大於x,且最小的數)
Input
第一行為n,表示操作的個數,下面n行每行有兩個數opt和x,opt表示操作的序號(1<=opt<=6)
Output
對於操作3,4,5,6每行輸出一個數,表示對應答案
Sample Input
101 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
Sample Output
10646584185
492737
HINT
1.n的資料範圍:n<=1000002.每個數的資料範圍:[-2e9,2e9] 沒什麼說的,splay模板題。
程式碼:
#include<bits/stdc++.h> #define maxn 100005 using namespace std; typedef long long LL; int read() { char c;int sum=0,f=1;c=getchar(); while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0' && c<='9'){sum=sum*10+c-'0';c=getchar();} return sum*f; } int n,opt,x; int fa[maxn],son[maxn][2],val[maxn],cnt[maxn],size[maxn],sz,root; void clear(int x) { son[x][1]=son[x][0]=fa[x]=val[x]=cnt[x]=size[x]=0; } bool getson(int x) { return son[fa[x]][1]==x; } void pushup(int x) { if(x) { size[x]=cnt[x]; if(son[x][0]) size[x]+=size[son[x][0]]; if(son[x][1]) size[x]+=size[son[x][1]]; } } void rotate(int x) { int y=fa[x],z=fa[y],s=getson(x); son[y][s]=son[x][s^1];fa[son[y][s]]=y; fa[y]=x;son[x][s^1]=y; fa[x]=z; if(z) son[z][son[z][1]==y]=x; pushup(y);pushup(x); } void splay(int x,int k) { for(int y;(y=fa[x])!=k;rotate(x)) if(fa[y]!=k) rotate((getson(x)==getson(y))?y:x); if(!k) root=x; } void insert(int x) { if(root==0) { sz++;root=sz; son[sz][0]=son[sz][1]=fa[sz]=0; val[sz]=x;size[sz]=cnt[sz]=1; return; } int now=root,f=0; while(1) { if(val[now]==x){cnt[now]++;pushup(now);pushup(f);splay(now,0);break;} f=now; now=son[now][val[now]<x]; if(now==0) { sz++; son[sz][0]=son[sz][1]=0;fa[sz]=f; val[sz]=x;size[sz]=cnt[sz]=1; son[f][val[f]<x]=sz; pushup(f); splay(sz,0); break; } } } int find(int x) { int ans=0,now=root; while(1) { if(x<val[now]) now=son[now][0]; else { ans+=(son[now][0]?size[son[now][0]]:0); if(x==val[now]) { splay(now,0); return ans+1; } ans+=cnt[now]; now=son[now][1]; } } } int findx(int x) { int now=root; while(1) { if(son[now][0] && x<=size[son[now][0]]) now=son[now][0]; else { int temp=(son[now][0]?size[son[now][0]]:0)+cnt[now]; if(x<=temp) return val[now]; x-=temp; now=son[now][1]; } } } int pre() { int now=son[root][0]; while(son[now][1]) now=son[now][1]; return now; } int nex() { int now=son[root][1]; while(son[now][0]) now=son[now][0]; return now; } void del(int x) { find(x); if(cnt[root]>1){cnt[root]--;return;} if(!son[root][0] && !son[root][1]){clear(root);root=0;return;} int oldroot=root; if(!son[root][0]) { root=son[root][1];fa[root]=0;clear(oldroot);return; } else if(!son[root][1]) { root=son[root][0];fa[root]=0;clear(oldroot);return; } splay(pre(),0); fa[son[oldroot][1]]=root; son[root][1]=son[oldroot][1]; clear(oldroot);pushup(root); } int main() { n=read(); for(int i=1;i<=n;i++) { opt=read();x=read(); switch (opt) { case 1:insert(x);break; case 2:del(x);break; case 3:printf("%d\n",find(x));break; case 4:printf("%d\n",findx(x));break; case 5:insert(x);printf("%d\n",val[pre()]);del(x);break; case 6:insert(x);printf("%d\n",val[nex()]);del(x);break; } } return 0; }