bzoj 3224
3224: Tyvj 1728 普通平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 16656 Solved: 7255
[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.每个数的数据范围:[-2e9,2e9]
Source
贴模板:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int MAXN=1000009; int fa[MAXN],ch[MAXN][2],key[MAXN],cnt[MAXN],size[MAXN],root,sz; void init() { root=sz=0; memset(ch,0,sizeof(ch)); memset(fa,0,sizeof(fa)); memset(cnt,0,sizeof(cnt)); memset(size,0,sizeof(size)); } inline void clear(int x) { fa[x]=ch[x][0]=ch[x][1]=cnt[x]=size[x]=0; } inline int get(int x) { return ch[fa[x]][1]==x; } inline void update(int x) { if(x){ size[x]=cnt[x]; if(ch[x][0]) size[x]+=size[ch[x][0]]; if(ch[x][1]) size[x]+=size[ch[x][1]]; } } inline void rotate(int x) { int father=fa[x],ffather=fa[father],which=get(x); ch[father][which]=ch[x][!which];fa[ch[father][which]]=father; ch[x][!which]=father;fa[father]=x; fa[x]=ffather; if(ffather) ch[ffather][ch[ffather][1]==father]=x; update(father); update(x); } inline void splay(int x) { for(int father;(father=fa[x]);rotate(x)) if(fa[father]) rotate((get(x)==get(father)?father:x)); root=x; } inline void insert(int x) { if(root==0) { root=++sz;fa[sz]=ch[sz][0]=ch[sz][1]=0;cnt[sz]=size[sz]=1;key[sz]=x;return; } int now=root,father=0; while(1){ if(key[now]==x) { cnt[now]++;update(now);update(father);splay(now);return; } father=now; now=ch[father][key[now]<x]; if(now==0){ sz++; fa[sz]=father; ch[father][key[father]<x]=sz; ch[sz][0]=ch[sz][1]=0; cnt[sz]=size[sz]=1; key[sz]=x; update(father); splay(sz); return; } } } inline int find(int x)//找到x的位置 { int now=root,ans=0; while(1){ if(x<key[now]) now=ch[now][0]; else{ if(ch[now][0]) ans+=size[ch[now][0]]; if(x==key[now]) { splay(now);return ans+1; } ans+=cnt[now]; now=ch[now][1]; } } } inline int rank(int x)//找到排名为x的数 { int now=root; while(1){ if(ch[now][0]&&x<=size[ch[now][0]]) now=ch[now][0]; else{ int tmp=(ch[now][0]?size[ch[now][0]]:0)+cnt[now]; if(x<=tmp) return key[now]; x=x-tmp; now=ch[now][1]; } } } inline int pre()//找前驱 { int now=ch[root][0]; while(ch[now][1]) now=ch[now][1]; return now; } inline int suf()//找后继 { int now=ch[root][1]; while(ch[now][0]) now=ch[now][0]; return now; } inline void del(int x)//删去一个x { find(x); if(cnt[root]>1) { cnt[root]--;update(root);return; } else if(!ch[root][0]&&!ch[root][1]) { root=sz=0;clear(root);return; } else if(!ch[root][0]){ int oldroot=root; root=ch[root][1]; fa[root]=0; clear(oldroot); return; }else if(!ch[root][1]){ int oldroot=root; root=ch[root][0]; fa[root]=0; clear(oldroot); return; } int leftbig=pre(),oldroot=root; splay(leftbig); ch[root][1]=ch[oldroot][1]; fa[ch[root][1]]=root; clear(oldroot); update(root); } int main() { //freopen("in.txt","r",stdin); int n,a,b; init(); scanf("%d",&n); while(n--){ scanf("%d%d",&a,&b); if(a==1) insert(b); else if(a==2) del(b); else if(a==3) printf("%d\n",find(b)); else if(a==4) printf("%d\n",rank(b)); else if(a==5) { insert(b);printf("%d\n",key[pre()]);del(b); } else if(a==6) { insert(b);printf("%d\n",key[suf()]);del(b); } } return 0; }