数据结构支持六种操作
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+7;
struct Tree{
int l,r;
int val,dat;
int cnt,size1;
}a[maxn];
int tot,root,inf=0x7fffffff;
int New(int val){
a[++tot].val=val;
a[tot].dat=rand();
a[tot].cnt=a[tot].size1=1;
return tot;
}
void updata(int p){
a[p].size1=a[a[p].l].size1+a[a[p].r].size1+a[p].cnt;
}
void build(){
New(-inf),New(inf);
root=1;
a[root].r=2;
}
void zig(int& p){
int q=a[p].l;
a[p].l=a[q].r;
a[q].r=p;
p=q;
updata(a[p].r);
updata(p);
}
void zag(int& p){
int q=a[p].r;
a[p].r=a[q].l;
a[q].l=p;
p=q;
updata(a[p].l);
updata(p);
}
void Insert(int& p,int val){
if(p==0){
p=New(val);
return ;
}
if(val==a[p].val){
++a[p].cnt;
updata(p);
return ;
}
if(val<a[p].val){
Insert(a[p].l,val);
if(a[p].dat<a[a[p].l].dat) zig(p);
}
else{
Insert(a[p].r,val);
if(a[p].dat<a[a[p].r].dat) zag(p);
}
updata(p);
}
void Remove(int& p,int val){
if(p==0) return ;
if(val==a[p].val){
if(a[p].cnt>1){
--a[p].cnt;
updata(p);
return ;
}
if(a[p].l||a[p].r){
if(a[p].r==0||a[a[p].l].dat>a[a[p].r].dat){
zig(p);
Remove(a[p].r,val);
}
else{
zag(p);
Remove(a[p].l,val);
}
updata(p);
}
else p=0;
return ;
}
val<a[p].val?Remove(a[p].l,val):Remove(a[p].r,val);
updata(p);
}
int getrank(int p,int val){
if(p==0) return 0;
if(val==a[p].val) return a[a[p].l].size1+1;
if(val<a[p].val) return getrank(a[p].l,val);
return getrank(a[p].r,val)+a[a[p].l].size1+a[p].cnt;
}
int getval(int p,int rank1){
if(p==0) return inf;
if(a[a[p].l].size1>=rank1) return getval(a[p].l,rank1);
if(a[a[p].l].size1+a[p].cnt>=rank1) return a[p].val;
return getval(a[p].r,rank1-a[a[p].l].size1-a[p].cnt);
}
int getpre(int val){
int p=root;
int ans=1;
while(p){
if(val==a[p].val){
if(a[p].l){
p=a[p].l;
while(a[p].r) p=a[p].r;
ans=p;
}
break;
}
if(val>a[p].val&&a[p].val>a[ans].val) ans=p;
p=(val>a[p].val?a[p].r:a[p].l);
}
return a[ans].val;
}
int getnext(int val){
int p=root;
int ans=2;
while(p){
if(val==a[p].val){
if(a[p].r){
p=a[p].r;
while(a[p].l) p=a[p].l;
ans=p;
}
break;
}
if(val<a[p].val&&a[p].val<a[ans].val) ans=p;
p=(val>a[p].val?a[p].r:a[p].l);
}
return a[ans].val;
}
int main(){
build();
int n;
scanf("%d",&n);
int id,x;
while(n--){
scanf("%d%d",&id,&x);
if(id==1){
Insert(root,x);
}
else if(id==2){
Remove(root,x);
}
else if(id==3){
printf("%d\n",getrank(root,x)-1);//负无穷占了一位;
}
else if(id==4){
printf("%d\n",getval(root,x+1));//负无穷占了最小位置;
}
else if(id==5){
printf("%d\n",getpre(x));
}
else{
printf("%d\n",getnext(x));
}
}
return 0;
}
权值线段树写法
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=1e5+7;
int a[maxn];
int m;
int sum[maxn<<2|1];
void quchong(int n){
sort(a+1,a+1+n);
m=unique(a+1,1+a+n)-a-1;
}
int getid(int x){
return lower_bound(a+1,a+1+m,x)-a;
}
void build(int l,int r,int k){
memset(sum,0,sizeof(sum));
}
void updata(int l,int r,int k,int id,int val){
if(l==r){
sum[k]+=val;
return ;
}
int mid=(l+r)>>1;
if(id<=mid) updata(l,mid,k<<1,id,val);
else updata(mid+1,r,k<<1|1,id,val);
sum[k]=sum[k<<1]+sum[k<<1|1];
}
//查询排名为x的数
int myfind_x(int l,int r,int k,int x){
if(l==r) return l;
int mid=(l+r)>>1;
if(sum[k<<1]>=x) return myfind_x(l,mid,k<<1,x);
return myfind_x(mid+1,r,k<<1|1,x-sum[k<<1]);
}
//[L,R] 区间内的所有数的次数和;
int myfind_h(int L,int R,int l,int r,int k){
if(L>R) return 0;
if(l>=L&&r<=R) return sum[k];
int mid=(l+r)>>1;
int res=0;
if(L<=mid) res+=myfind_h(L,R,l,mid,k<<1);
if(R>mid) res+=myfind_h(L,R,mid+1,r,k<<1|1);
return res;
}
struct Node{
int id;
int x;
}b[maxn];
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%d%d",&b[i].id,&b[i].x);
a[i]=b[i].x;
}
quchong(n);
for(int i=1;i<=n;++i){
if(b[i].id==1) updata(1,m,1,getid(b[i].x),1);
else if(b[i].id==2) updata(1,m,1,getid(b[i].x),-1);
else if(b[i].id==3) printf("%d\n",myfind_h(1,getid(b[i].x)-1,1,m,1)+1);
else if(b[i].id==4) printf("%d\n",a[myfind_x(1,m,1,b[i].x)]);
else if(b[i].id==5) printf("%d\n",a[myfind_x(1,m,1,myfind_h(1,getid(b[i].x)-1,1,m,1))]);
else printf("%d\n",a[myfind_x(1,m,1,myfind_h(1,getid(b[i].x),1,m,1)+1)]);
}
return 0;
}