可持久化线段树 1(主席树模板)
Posted hsez-cyx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了可持久化线段树 1(主席树模板)相关的知识,希望对你有一定的参考价值。
(本人的模板)
Description
题目背景
这是个非常经典的主席树入门题——静态区间第 kk 小数据已经过加强,请使用主席树。同时请注意常数优化
题目描述
如题,给定 nn 个整数构成的序列,将对于指定的闭区间查询其区间内的第 kk 小值。
输入格式
第一行包含两个正整数 n,mn,m,分别表示序列的长度和查询的个数。第二行包含 nn 个整数,表示这个序列各项的数字。接下来 mm 行每行包含三个整数 l, r, kl,r,k , 表示查询区间 [l, r][l,r] 内的第 kk 小值。
输出格式
输出包含 kk 行,每行一个整数,依次表示每一次查询的结果
Code
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int N=2e5+10;
struct node
{
int lc,rc,sum;
}f[N*40];
struct mode
{
int v,id;
bool operator <(const mode &o)const
{
return v<o.v;
}
}a[N];
int n,m,rt[N],d[N],l,r,k,tot,cnt,re[N];
void build(int l,int r,int &x,int y,int pos)
{
x=++tot;
f[x]=f[y],f[x].sum++;
if(l==r) return ;
int mid=(l+r)>>1;
if(pos<=mid) build(l,mid,f[x].lc,f[y].lc,pos);
else build(mid+1,r,f[x].rc,f[y].rc,pos);
}
int ans(int l,int r,int x,int y,int k)
{
if(l>=r) return l;
int cnt=f[f[x].lc].sum-f[f[y].lc].sum;
int mid=(l+r)>>1;
if(cnt>=k) return ans(l,mid,f[x].lc,f[y].lc,k);
else return ans(mid+1,r,f[x].rc,f[y].rc,k-cnt);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i].v),a[i].id=i;
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)
{
if(i==1 || a[i].v!=a[i-1].v) re[++cnt]=a[i].v;
d[a[i].id]=cnt;
}
for(int i=1;i<=n;i++) build(1,n,rt[i],rt[i-1],d[i]);
while(m--)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d
",re[ans(1,n,rt[r],rt[l-1],k)]);
}
return 0;
}
以上是关于可持久化线段树 1(主席树模板)的主要内容,如果未能解决你的问题,请参考以下文章