码迷,mamicode.com
首页 > 其他好文 > 详细

可持久化线段树 1(主席树模板)

时间:2020-02-06 12:50:58      阅读:61      评论:0      收藏:0      [点我收藏+]

标签:tor   注意   ble   das   RKE   span   algorithm   desc   经典   

【模板】可持久化线段树 1(主席树)(luogu)

(本人的模板)

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\n",re[ans(1,n,rt[r],rt[l-1],k)]);
    }
    return 0;
}

 

可持久化线段树 1(主席树模板)

标签:tor   注意   ble   das   RKE   span   algorithm   desc   经典   

原文地址:https://www.cnblogs.com/hsez-cyx/p/12267989.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!