C50【模板】可持久化线段树(主席树)P3834 静态区间第 k 小

视频链接:C50【模板】可持久化线段树(主席树)P3834 静态区间第 k 小_哔哩哔哩_bilibili

 

 

 

 

 

Luogu P3834 【模板】可持久化线段树2

//权值线段树+离散化+动态开点 nlogn
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

#define N 200005
#define mid ((l+r)>>1)
int n,m,a[N],b[N];
int root[N],tot; //根节点,节点个数
int ls[N*20],rs[N*20],sum[N*20];
//sum:区间数的出现次数之和

void build(int &u,int l,int r){ //建空树
  u=++tot; //动态开点
  if(l==r)return;
  build(ls[u],l,mid);
  build(rs[u],mid+1,r);
}
void change(int &u,int v,int l,int r,int p){ //点修
  u=++tot; //动态开点
  ls[u]=ls[v]; rs[u]=rs[v]; sum[u]=sum[v]+1;
  if(l==r) return;    //双指针同步搜索
  if(p<=mid) change(ls[u],ls[v],l,mid,p);
  else change(rs[u],rs[v],mid+1,r,p);
}
int query(int u,int v,int l,int r,int k){ //点查
  if(l==r)return l;   //双指针同步搜索
  int s=sum[ls[u]]-sum[ls[v]];
  if(k<=s)return query(ls[u],ls[v],l,mid,k);
  else return query(rs[u],rs[v],mid+1,r,k-s);
}
int main(){
  scanf("%d%d",&n,&m);
  for(int i=1; i<=n; i++)
    scanf("%d",&a[i]),b[i]=a[i];
  sort(b+1,b+n+1);
  int bn=unique(b+1,b+n+1)-b-1; //去重
  // build(root[0],1,bn);
  for(int i=1; i<=n; i++){
    int p=lower_bound(b+1,b+bn+1,a[i])-b;
    change(root[i],root[i-1],1,bn,p);
  }
  while(m--){
    int l,r,k; scanf("%d%d%d",&l,&r,&k);
    int p=query(root[r],root[l-1],1,bn,k);
    printf("%d\n",b[p]);
  }
  return 0;
}

 

//权值线段树+离散化+动态开点 nlogn
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

#define N 200005
#define ls(u) tr[u].l
#define rs(u) tr[u].r
#define mid ((l+r)>>1)
int n,m,a[N],b[N];
int root[N],tot; //根节点,节点个数
struct tree{
  int l,r,sum;   //区间数的出现次数之和
}tr[N*20];

void build(int &u,int l,int r){ //建空树
  u=++tot; //动态开点
  if(l==r) return;
  build(ls(u),l,mid);
  build(rs(u),mid+1,r);
}
void change(int &u,int v,int l,int r,int p){ //点修
  u=++tot; //动态开点
  tr[u]=tr[v]; tr[u].sum++;
  if(l==r) return;      //双指针同步搜索
  if(p<=mid) change(ls(u),ls(v),l,mid,p);
  else change(rs(u),rs(v),mid+1,r,p);
}
int query(int u,int v,int l,int r,int k){ //点查
  if(l==r) return l;    //双指针同步搜索
  int s=tr[ls(u)].sum-tr[ls(v)].sum;
  if(k<=s) return query(ls(u),ls(v),l,mid,k);
  else return query(rs(u),rs(v),mid+1,r,k-s);
}
int main(){
  scanf("%d%d",&n,&m);
  for(int i=1; i<=n; i++)
    scanf("%d",&a[i]), b[i]=a[i];
  sort(b+1,b+n+1);
  int bn=unique(b+1,b+n+1)-b-1; //去重
  // build(root[0],1,bn);
  for(int i=1; i<=n; i++){
    int p=lower_bound(b+1,b+bn+1,a[i])-b;
    change(root[i],root[i-1],1,bn,p);
  }
  while(m--){
    int l,r,k; scanf("%d%d%d",&l,&r,&k);
    int p=query(root[r],root[l-1],1,bn,k);
    printf("%d\n",b[p]);
  }
}

 

posted @ 2023-10-24 15:28  董晓  阅读(338)  评论(0编辑  收藏  举报