题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
- 插入xx数
- 删除xx数(若有多个相同的数,因只删除一个)
- 查询xx数的排名(排名定义为比当前数小的数的个数+1+1。若有多个相同的数,因输出最小的排名)
- 查询排名为xx的数
- 求xx的前驱(前驱定义为小于xx,且最大的数)
- 求xx的后继(后继定义为大于xx,且最小的数)
输入格式
第一行为nn,表示操作的个数,下面nn行每行有两个数optopt和xx,optopt表示操作的序号( 1 leq opt leq 61≤opt≤6 )
输出格式
对于操作3,4,5,63,4,5,6每行输出一个数,表示对应答案
输入输出样例
输入 #1
10 1 106465 4 1 1 317721 1 460929 1 644985 1 84185 1 89851 6 81968 1 492737 5 493598
输出 #1
View Code
106465 84185 492737
维护权值的平衡树模板题
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define ll long long #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) #define pb push_back #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) typedef pair<int,int>pii; ////////////////////////////////// const int N=2e6+10; int son[N][2],fa[N],siz[N],cnt[N],val[N],ncnt,root; int chk(int x) { return son[fa[x]][1]==x; } void up(int x) { siz[x]=siz[son[x][0]]+siz[son[x][1]]+cnt[x]; } void rotate(int x) { int y=fa[x],z=fa[y],k=chk(x),w=son[x][k^1]; son[y][k]=w;fa[w]=y; son[z][chk(y)]=x;fa[x]=z; son[x][k^1]=y;fa[y]=x; up(x);up(y); } void splay(int x,int goal=0) { while(fa[x]!=goal) { int y=fa[x],z=fa[y]; if(z!=goal) { if(chk(y)==chk(z))rotate(y); else rotate(x); } rotate(x); } if(!goal)root=x; } void find(int x) { if(!root)return ; int pos=root; while(son[pos][x>val[pos]]&&x!=val[pos]) pos=son[pos][x>val[pos]]; splay(pos); } void insert(int x) { int pos=root,p=0; while(pos&&val[pos]!=x) { p=pos; pos=son[pos][x>val[pos]]; } if(pos)cnt[pos]++; else { pos=++ncnt; if(p)son[p][x>val[p]]=pos; son[pos][0]=son[pos][1]=0; val[pos]=x;fa[pos]=p; cnt[pos]=siz[pos]=1; } splay(pos); } int kth(int k) { int pos=root; while(1) { if(son[pos][0]&&siz[son[pos][0]]>=k) pos=son[pos][0]; else if(k>siz[son[pos][0]]+cnt[pos]) k-=siz[son[pos][0]]+cnt[pos],pos=son[pos][1]; else {splay(pos);return pos;} } } int pre(int x) { find(x); if(val[root]<x)return root; int pos=son[root][0]; while(son[pos][1])pos=son[pos][1]; splay(pos);return pos; } int succ(int x) { find(x); if(val[root]>x)return root; int pos=son[root][1]; while(son[pos][0])pos=son[pos][0]; splay(pos);return pos; } void remove(int x) { int last=pre(x),nex=succ(x); splay(last);splay(nex,last); int pos=son[nex][0]; if(cnt[pos]>1) { cnt[pos]--;splay(pos); } else son[nex][0]=0; up(root);up(nex); } void rank1(int x) { find(x); if(val[root]<=x) printf("%d ",siz[son[root][0]]); else if(val[root]>x) printf("%d ",siz[son[root][0]]+cnt[root]); int main() { int m;cin>>m; int a,b; insert(0x3f3f3f3f); insert(0xcfcfcfcf); while(m--) { scanf("%d%d",&a,&b); if(a==1)insert(b); if(a==2)remove(b); if(a==3)rank1(b); if(a==4)printf("%d ", val[kth(b+1)] ); if(a==5)printf("%d ",val[pre(b)]); if(a==6)printf("%d ",val[succ(b)]); } return 0; }