C47 权值线段树+离散化 P3369 普通平衡树
视频链接:233 权值线段树+离散化 P3369 普通平衡树_哔哩哔哩_bilibili
//权值线段树+离散化 nlogn #include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N=100005; #define ls u<<1 #define rs u<<1|1 #define mid ((l+r)>>1) int n,m,id; int opt[N],a[N],b[N]; //opt:操作序号 a:数x b:备份数组 int sum[N<<2]; //区间数的出现次数之和 void pushup(int u){ //上传 sum[u]=sum[ls]+sum[rs]; } void change(int u,int l,int r,int x,int k){ //插删即点修 if(l==r){sum[u]+=k; return;} if(x<=mid) change(ls,l,mid,x,k); else change(rs,mid+1,r,x,k); pushup(u); } int q_rank(int u,int l,int r,int x,int y){ //排名即前缀和 if(x<=l && r<=y) return sum[u]; int s=0; if(x<=mid) s+=q_rank(ls,l,mid,x,y); if(y>mid) s+=q_rank(rs,mid+1,r,x,y); return s; } int q_num(int u,int l,int r,int x){ //排名x的数 if(l==r) return l; if(x<=sum[ls]) return q_num(ls,l,mid,x); else return q_num(rs,mid+1,r,x-sum[ls]); } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d",&opt[i],&a[i]); if(opt[i]!=4) b[++m]=a[i]; //备份 } sort(b+1,b+m+1); //排序 m=unique(b+1,b+1+m)-b-1; //去重 for(int i=1;i<=n;i++){ if(opt[i]!=4) id=lower_bound(b+1,b+m+1,a[i])-b; if(opt[i]==1) change(1,1,m,id,1); //插入x if(opt[i]==2) change(1,1,m,id,-1); //删除x if(opt[i]==3) //x的排名 printf("%d\n",id>1?q_rank(1,1,m,1,id-1)+1:1); if(opt[i]==4) //排名为x的数 printf("%d\n",b[q_num(1,1,m,a[i])]); if(opt[i]==5){ //x的前驱 int rk=q_rank(1,1,m,1,id-1); printf("%d\n",b[q_num(1,1,m,rk)]); } if(opt[i]==6){ //x的后继 int rk=q_rank(1,1,m,1,id)+1; printf("%d\n",b[q_num(1,1,m,rk)]); } } }