[模板] 主席树

谴责奶人的HSZ巨神
静态版本 求区间第k大

可持久化也没那么高大上嘛,主席树本质上就是多棵线段树,求第k大就类似平衡树的第k大。

//Stay foolish,stay hungry,stay young,stay simple
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cctype>

using namespace std;

const int MAXN=200009,M=5000009;

int P,a[MAXN],b[MAXN],rt[MAXN],lc[M],rc[M],s[M];

inline int rd(){
    int ret=0,f=1;char c;
    while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
    while(isdigit(c)){
        ret=ret*10+c-'0';
        c=getchar();
    }
    return ret*f;
}

int n,m;

void build(int&t,int l,int r)
{
    t=++P;
    if(l!=r)
    {
        int m=(l+r)>>1;
        build(lc[t],l,m);
        build(rc[t],m+1,r);
    }
}

inline void insert(int*t,int u,int l,int r,int v)
{
    while(l!=r)
    {
        s[*t=++P]=s[u]+1;
        int m=(l+r)>>1;
        if(v<=m) r=m,rc[*t]=rc[u],t=&lc[*t],u=lc[u];
        else  l=m+1,lc[*t]=lc[u],t=&rc[*t],u=rc[u];
    }
    s[*t=++P]=s[u]+1;
}
inline int ask(int t,int u,int l,int r,int k)
{
    while(l!=r)
    {
        int m=(l+r)>>1;
        int v=s[lc[u]]-s[lc[t]];
        if(k<=v) r=m,t=lc[t],u=lc[u];
        else     l=m+1,t=rc[t],u=rc[u],k-=v;
    }
    return b[l];
}
int main()
{
    n=rd();
    m=rd();
    for(int i=1;i<=n;i++)
        a[i]=rd(),b[i]=a[i];
    sort(b+1,b+n+1);
    int tot=unique(b+1,b+n+1)-b-1;//离散化
    build(rt[0],1,tot);
    for(int i=1;i<=n;i++)
        insert(&rt[i],rt[i-1],1,tot,lower_bound(b+1,b+tot+1,a[i])-b);
    for(int i=1;i<=m;i++){
        int x,y,k;
        x=rd();y=rd();k=rd();
        printf("%d\n",ask(rt[x-1],rt[y],1,tot,k)); 
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/gh0stcai/article/details/80140433