主席树板子

区间第K大

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=2e5+4;
int n,m,cnt,root[maxn],a[maxn],x,y,k;
struct node{int l,r,sum;}tr[maxn*40];
vector<int> ve;
int getid(int x) {
    return lower_bound(ve.begin(),ve.end(),x)-ve.begin()+1;
}
inline void update(int l,int r,int &x,int y,int pos){
    tr[++cnt]=tr[y],tr[cnt].sum++,x=cnt;
    if(l==r) return;
    int mid=(l+r)>>1;
    if(pos<=mid) update(l,mid,tr[x].l,tr[y].l,pos);
    else update(mid+1,r,tr[x].r,tr[y].r,pos);
}
inline int query(int l,int r,int x,int y,int k){
    if(l==r) return l;
    int mid=(l+r)>>1;
    int sum=tr[tr[y].l].sum-tr[tr[x].l].sum;
    if(sum>=k) return query(l,mid,tr[x].l,tr[y].l,k);
    else return query(mid+1,r,tr[x].r,tr[y].r,k-sum);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),ve.push_back(a[i]);
    sort(ve.begin(),ve.end());
    ve.erase(unique(ve.begin(),ve.end()),ve.end());
    for(int i=1;i<=n;i++) update(1,n,root[i],root[i-1],getid(a[i]));
    for(int i=1;i<=m;i++){
        int x,y,k;
        scanf("%d%d%d",&x,&y,&k);
        printf("%d\n",ve[query(1,n,root[x-1],root[y],k)-1]);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wifimonster/p/10238482.html
今日推荐