sw抄来的主席树

//本模板是离散后对权值建树
#include<bits/stdc++.h>
#define mid (l+r>>1)
using namespace std;
const int N=2e5+10;
struct TR
{
    int sum,lo,ro;
}tr[N<<5];
int tr_cnt;//之后需要初始化=0
int n,m,q,arr[N],brr[N],rt[N];//m是权值的数量
void build(int &o,int l=1,int r=m)
{
    o=++tr_cnt;
    //tr[o].sum=0;
    if(l==r)return;
    build(tr[o].lo,l,mid);
    build(tr[o].ro,mid+1,r);
}
void update(int p,int v,int pre,int &o,int l=1,int r=m)
{
    o=++tr_cnt;
    tr[o]=tr[pre];
    tr[o].sum+=v;//都是+1
    if(l==r)return;
    if(p<=mid)update(p,v,tr[pre].lo,tr[o].lo,l,mid);
    else update(p,v,tr[pre].ro,tr[o].ro,mid+1,r);
}
//u和v是两个线段树的根,相减后的线段树求第k个的下标位置
int query(int k,int u,int v,int l=1,int r=m)
{
    if(l==r)return l;
 
    int tmp=tr[tr[v].lo].sum-tr[tr[u].lo].sum;
    if(tmp>=k)return query(k,tr[u].lo,tr[v].lo,l,mid);
    else return query(k-tmp,tr[u].ro,tr[v].ro,mid+1,r);
}
int main()
{
    int n,q;scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)scanf("%d",arr+i),brr[i]=arr[i];
    sort(brr+1,brr+1+n);
    m=unique(brr+1,brr+1+n)-brr-1;
 
    build(rt[0]);
    for(int i=1;i<=n;i++)
    {
        int p=lower_bound(brr+1,brr+1+m,arr[i])-brr;
        update(p,1,rt[i-1],rt[i]);
    }
    while(q--)
    {
        int u,v,k;
        scanf("%d%d%d",&u,&v,&k);
        printf("%d
",brr[query(k,rt[u-1],rt[v])]);
    }
	return 0;
}

  

rush!
原文地址:https://www.cnblogs.com/LH2000/p/14659789.html