bzoj3224 普通平衡树(splay 模板)
3224: Tyvj 1728 普通平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 11427 Solved: 4878
[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
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
Sample Output
106465
84185
492737
84185
492737
HINT
1.n的数据范围:n<=100000
2.每个数的数据范围:[-1e7,1e7]
数据如下http://pan.baidu.com/s/1jHMJwO2
Source
#include <cstdio> #define Maxn 1000000 using namespace std; int f[Maxn];//father int ch[Maxn][2];//child ; 0 for left ; 1 for right int key[Maxn];//key int cnt[Maxn];//value int siz[Maxn];//size of subtree int sz,root;//size of tree and root //clear the ndoe void clear(int x) { ch[x][0]=ch[x][1]=f[x]=cnt[x]=key[x]=siz[x]=0; } //rightson return 1;left son return 0 int getson(int x) { return ch[f[x]][1]==x; } //update the size void update(int x) { siz[x]=cnt[x]; if (ch[x][0]) siz[x]+=siz[ch[x][0]]; if (ch[x][1]) siz[x]+=siz[ch[x][1]]; } //retation int rotate(int x) { int fa=f[x],fafa=f[fa],k=getson(x); ch[fa][k]=ch[x][k^1];f[ch[fa][k]]=fa; ch[x][k^1]=fa;f[fa]=x; f[x]=fafa; if (fafa) ch[fafa][ch[fafa][1]==fa]=x; update(fa);update(x); } //rotate until x is the root void splay(int x) { for (int fa;fa=f[x];rotate(x)) if (f[fa]) rotate(getson(x)==getson(fa) ? fa : x); root=x; } int pre() { int now=ch[root][0]; while(ch[now][1]) now=ch[now][1]; return now; } int nex() { int now=ch[root][1]; while(ch[now][0]) now=ch[now][0]; return now; } //find x's pos int findpos(int v) { int now=root,ans=0; while(1) { if (v<key[now]) now=ch[now][0]; else { ans+=ch[now][0]?siz[ch[now][0]]:0; if (v==key[now]) { splay(now); return ans+1; } ans+=cnt[now]; now=ch[now][1]; } } } //find pos's x int findx(int x) { int now=root; while(1) { if (ch[now][0] && x<=siz[ch[now][0]]) now=ch[now][0]; else { int temp=(ch[now][0]?siz[ch[now][0]]:0)+cnt[now]; if (x<=temp) return key[now]; x-=temp; now=ch[now][1]; } } } //ceate a new splay node void create(int v) { sz++; ch[sz][0]=ch[sz][1]=f[sz]=0; key[sz]=v; cnt[sz]=1; siz[sz]=1; //root=sz; } //insert a node void insert(int v) { if (!root) create(v),root=sz; else { int now=root,fa=0; while(1) { if (key[now]==v) { cnt[now]++; update(now);update(fa); splay(now); break; } fa=now; now=ch[fa][v>key[fa]]; if (!now) { create(v); f[sz]=fa; ch[fa][v>key[fa]]=sz; update(fa); splay(sz); break; } } } } void del(int x) { int t=findpos(x); if (cnt[root]>1) { cnt[root]--; update(root); return; } //none if (!ch[root][0] && !ch[root][1]) { clear(root); root=0; return; } //one if (!ch[root][1]) { int temp=root; root=ch[root][0]; f[root]=0; clear(temp); return; } else if (!ch[root][0]) { int temp=root; root=ch[root][1]; f[root]=0; clear(temp); return; } //two int pre1=pre(),temp=root; splay(pre1); f[ch[temp][1]]=root; ch[root][1]=ch[temp][1]; clear(temp); update(root); } int main() { int n,opt,x; scanf("%d",&n); for (int i=1;i<=n;++i) { scanf("%d%d",&opt,&x); switch(opt) { case 1: insert(x); break; case 2: del(x); break; case 3: printf("%d\n",findpos(x)); break; case 4: printf("%d\n",findx(x)); break; case 5: insert(x); printf("%d\n",key[pre()]); del(x); break; case 6: insert(x); printf("%d\n",key[nex()]); del(x); break; } } }
#include<iostream> #include<cstdio> #include<cstring> #define N 1000000 using namespace std; int f[N],ch[N][2],key[N],cnt[N],siz[N],sz,root; inline int read() { int x=0,f=1;char c=getchar(); while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } inline void update(int x) { siz[x]=cnt[x]; if(ch[x][0]) siz[x]+=siz[ch[x][0]]; if(ch[x][1]) siz[x]+=siz[ch[x][1]]; } int pre() { int now=ch[root][0]; while(ch[now][1]) now=ch[now][1];return now; } int nex() { int now=ch[root][1]; while(ch[now][0]) now=ch[now][0];return now; } inline int getson(int x) { return ch[f[x]][1]==x; } inline void rorate(int x) { int fa=f[x],ffa=f[fa],k=getson(x); ch[fa][k]=ch[x][k^1];f[ch[fa][k]]=fa; ch[x][k^1]=fa;f[fa]=x;f[x]=ffa; if(ffa)ch[ffa][ch[ffa][1]==fa]=x; update(fa);update(x); } void splay(int x) { for(int fa;fa=f[x];rorate(x)) if(f[fa]) rorate(getson(x)==getson(fa)?fa:x); root=x; } int findpos(int x) { int now=root,ans=0; while(1) { if(x<key[now]) now=ch[now][0]; else { ans+=ch[now][0]?siz[ch[now][0]]:0; if(x==key[now]) { splay(now);return ans+1; } ans+=cnt[now];now=ch[now][1]; } } } int findx(int x) { int now=root; while(1) { if(ch[now][0]&&x<=siz[ch[now][0]]) now=ch[now][0]; else { int tmp=(ch[now][0]?siz[ch[now][0]]:0)+cnt[now]; if(x<=tmp) return key[now]; x-=tmp;now=ch[now][1]; } } } void clear(int x) { ch[x][0]=ch[x][1]=cnt[x]=siz[x]=key[x]=f[x]=0; } void creat(int x) { sz=sz+1;key[sz]=x;cnt[sz]=siz[sz]=1; ch[sz][0]=ch[sz][1]=f[sz]=0; } void insert(int x) { if(!root) creat(x),root=sz; else { int now=root,fa=0; while(1) { if(key[now]==x) { cnt[now]++;siz[now]++;splay(now); break; } fa=now;now=ch[fa][x>key[fa]]; if(!now) { creat(x);f[sz]=fa;ch[fa][x>key[fa]]=sz; splay(sz);break; } } } } void del(int x) { int t=findpos(x); if(cnt[root]>1) { cnt[root]--;siz[root]--;return; } if(!ch[root][0]&&!ch[root][1]) { clear(root);root=0;return; } if(!ch[root][0]) { int tmp=root;root=ch[root][1];f[root]=0; clear(tmp);return; } if(!ch[root][1]) { int tmp=root;root=ch[root][0];f[root]=0; clear(tmp);return; } int pre1=pre(),tmp=root;splay(pre1); ch[root][1]=ch[tmp][1];f[ch[tmp][1]]=root; clear(tmp);update(root); } int main() { int n,opt,x; 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",findpos(x));break; case 4 :printf("%d\n",findx(x));break; case 5 :insert(x);printf("%d\n",key[pre()]);del(x);break; case 6 :insert(x);printf("%d\n",key[nex()]);del(x);break; } } }
折花枝,恨花枝,准拟花开人共卮,开时人去时。
怕相思,已相思,轮到相思没处辞,眉间露一丝。