hdu 2665 主席树(静态)求区间第k小模板题

模板

 

#include <bits/stdc++.h>
using namespace std;
const int M = 1e5+7;
int _,n,q,a[M],ls[M];
int L[M*20],R[M*20],num[M*20],T[M],tot,pos;//L每个节点的左子树,R每个节点的右子树,T存所有的节点
void build(int l,int r,int &rt){
    rt=++tot;
    num[rt]=0;//空树没有数字存在
    if(l==r){
        return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,L[rt]);
    build(mid+1,r,R[rt]);
}
void update(int l,int r,int &rt,int prert){
    rt=++tot;
    num[rt]=(num[prert]+1);//比上一颗树数字个数多1
    if(l==r){
        return ;
    }
    int mid=(l+r)>>1;
    if(pos<=mid){
        R[rt]=R[prert];//只有更新左子树,右子树状态和上一颗树一样
        update(l,mid,L[rt],L[prert]);
    }
    else{
        L[rt]=L[prert];//只更新右子树,左子树状态和上一颗树一样
        update(mid+1,r,R[rt],R[prert]);
    }
}
int query(int l,int r,int lrt,int rrt,int k){
    if(l==r){
        return l;
    }
    int mid=(l+r)>>1;
    int sum=num[L[rrt]]-num[L[lrt]];//第r棵树减去第l-1棵树就是当前查询区间的数字个数
    if(sum>=k) return query(l,mid,L[lrt],L[rrt],k);
    else return query(mid+1,r,R[lrt],R[rrt],k-sum);
}
void solve(){
    sort(ls+1,ls+n+1);
    int sz=unique(ls+1,ls+n+1)-ls-1;//去重离散化
    build(1,sz,T[0]);//建空树
    for(int i=1;i<=n;i++){
        pos=lower_bound(ls+1,ls+sz+1,a[i])-ls;
        update(1,sz,T[i],T[i-1]);
    }
    while(q--){
        int l,r,k,ans;
        scanf("%d%d%d",&l,&r,&k);
        printf("%d\n",ls[query(1,sz,T[l-1],T[r],k)]);//查询的区间的状态由第r棵树减第l-1棵树得到
    }
}
int main(){
    scanf("%d",&_);
    while(_--){
        scanf("%d%d",&n,&q);tot=0;
        for(int i=1;i<=n;i++) scanf("%d",&a[i]),ls[i]=a[i];
        solve();
    }
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/LMissher/p/9564188.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值