http://www.lydsy.com/JudgeOnline/problem.php?id=3224
由于平衡树不太会写,就写棵线段树凑合着
就开棵值域线段树,
添加/删除,就是在包含改数的区间节点+1/-1
询问某数的排名时,就是经过右节点时,把左边子树的值加上
询问某排名的数时,就是类似求kth时的操作
询问某数前驱后继时,询问某数排名,在对该排名进行访问kth
#include<cstdio> #include<algorithm> #define FOR(i,s,t) for(register int i=s;i<=t;++i) #define ls k<<1,l,mid #define rs k<<1|1,mid+1,r #define gc getchar() using namespace std; const int N=400011; int n,p; int a[N],b[N],c[N]; namespace Segment_Tree{ int tr[N]; inline void modify(int x,int v,int k=1,int l=1,int r=c[0]){ tr[k]+=v; if(l==r)return ; int mid=(l+r)>>1; x<=mid?modify(x,v,ls):modify(x,v,rs); } inline int query_num(int x,int k=1,int l=1,int r=c[0]){ if(l==r)return l; int mid=(l+r)>>1; return x<=tr[k<<1]?query_num(x,ls):query_num(x-tr[k<<1],rs); } inline int query_pos(int x,int type,int k=1,int l=1,int r=c[0]){ if(l==r){ if(type==3)return 1; if(type==5)return 0; if(type==6)return tr[k]+1; } int mid=(l+r)>>1; return x<=mid?query_pos(x,type,ls):(tr[k<<1]+query_pos(x,type,rs)); } } using namespace Segment_Tree; inline void disc_init(){ sort(c+1,c+c[0]+1); c[0]=unique(c+1,c+c[0]+1)-c-1; FOR(i,1,n) if(a[i]!=4)b[i]=lower_bound(c+1,c+c[0]+1,b[i])-c; } inline int read(){ char c;while(c=gc,c==' '||c==' ');int data=0,f=1; c=='-'?f=-1:data=c-48; while(c=gc,c>='0'&&c<='9')data=(data<<1)+(data<<3)+c-48; return data*f; } int main(){ n=read(); FOR(i,1,n){ a[i]=read();b[i]=read(); if(a[i]!=4)c[++c[0]]=b[i]; } disc_init(); FOR(i,1,n){ if(a[i]==1)modify(b[i],1); if(a[i]==2)modify(b[i],-1); if(a[i]==3)printf("%d ",query_pos(b[i],3)); if(a[i]==4)printf("%d ",c[query_num(b[i])]); if(a[i]==5)printf("%d ",c[query_num(query_pos(b[i],5))]); if(a[i]==6)printf("%d ",c[query_num(query_pos(b[i],6))]); } return 0; }