主席树
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
以上是关于主席树的主要内容,如果未能解决你的问题,请参考以下文章