主席树

Posted ljy08163268

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了主席树相关的知识,希望对你有一定的参考价值。

/*

 主席树做法,查询区间第K大,输入的l,r是从0开始

 区间第K大解法:https://www.cnblogs.com/GoldenFingers/p/9475172.html

 */

#include <iostream>

#include <stdio.h>

#include <string.h>

#include <stack>

#include <map>

#include <vector>

#include <algorithm>

using namespace std;

typedef long long ll;

const int maxn=5e4+10;

vector<int>v;

int rt[maxn*20],ls[maxn*20],rs[maxn*20],sum[maxn*20];

int tot,sz;

int a[maxn],b[maxn];

void build(int &root,int l,int r){

    root = ++tot;

    sum[root]=0;

    if(l==r)return ;

    int mid=(l+r)/2;

    build(ls[root],l,mid);

    build(rs[root],mid+1,r);

}

void update(int &root,int l,int r,int last,int p){

    root=++tot;

    ls[root]=ls[last];

    rs[root]=rs[last];

    sum[root]=sum[last]+1;

    if(l==r)return ;

    int mid=(l+r)/2;

    if(p<=mid)update(ls[root],l,mid,ls[last],p);

    else update(rs[root],mid+1,r,rs[last],p);

}

void init(int n){

    for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i];

    sort(b+1,b+1+n);

    sz=(int)(unique(b+1, b+1+n)-(b+1));

    tot=0;

    build(rt[0],1,sz);

    for(int i=1;i<=n;i++){

        int pos=(int)(lower_bound(b+1, b+1+sz, a[i])- b);

        update(rt[i],1,sz,rt[i-1],pos);

    }

}

int query(int ql,int qr,int l,int r,int k){

    if(l==r)return l;

    int mid=(l+r)/2;

    int cnt=sum[ls[qr]]-sum[ls[ql]];

    if(k<=cnt)return query(ls[ql],ls[qr],l,mid,k);

    else return query(rs[ql],rs[qr],mid+1,r,k-cnt);

}

int main(){

    int n,q;

    scanf("%d",&n);

    init(n);

    scanf("%d",&q);

    while(q--){

        int l,r,k;

        scanf("%d%d%d",&l,&r,&k);

        l++; r++;

        int id=query(rt[l-1],rt[r],1,sz,r-l+1-k+1);

        printf("%d ",b[id]);

    }

    return 0;

}

地址:https://www.cnblogs.com/zyf0163/p/4749042.html

以上是关于主席树的主要内容,如果未能解决你的问题,请参考以下文章

主席树小结

带修改的主席树

可持久化线段树(主席树)

[知识学习] 主席树

BZOJ 2588 Spoj 10628 Count on a tree | 树上主席树

主席树(入门篇)