C47 权值线段树+离散化 P3369 普通平衡树

视频链接:233 权值线段树+离散化 P3369 普通平衡树_哔哩哔哩_bilibili

 

 

Luogu P3369 【模板】普通平衡树

//权值线段树+离散化 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)]);
    }
  }
}

 

posted @ 2023-10-20 21:06  董晓  阅读(209)  评论(0编辑  收藏  举报