主席树(模板)

Posted whff521

tags:

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

求区间第K大的值;

我们需要在短时间内回答数目巨大的问题,这个算法的核心是空间换时间;

每个点建一个线段树,是的;

我们先离散化所有权值,使得当前的权值在1到n范围内,恰巧是vector里的下标;

对于每一个点,我们分成左二子和右儿子,分别存放当前区间的左半部分和右半部分,维护左右节点的数量;

我们怎么求区间第K大呢?

运用前缀和的思想,我们其实建出来的很多树左右数量是递增的;

遍历每一个节点,现将当前节点继承前一节点的历史状态,再将节点数+1,根据当前节点的大小判断插在左边还是右边,递归进行此操作;

 

对于区间【l,r】,我们将l-1的树拿出来,r的树拿出来,每个树的节点数就是1到 i 的节点数,先两个左子树的节点数相减,得到的数与当前k比较,

如果大于k就在左子树里找,如果小于k就在右子树里找k-sum_L个;也是递归实现;

 

实质就是每次加点,查询时套用前缀和,根据数量判断向下递归的方向,从而减少时间复杂度;

时刻注意每个点代表的历史状态,谁和谁对应;

 

离散化操作

    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());

先将数组排序,然后unique(),此时函数操作是将重复的数字都扔到后面,返回不重复序列的最后一个数的下一个数的下标;这时我们将后面删去即可;

取得离散后的数lower_bound即可;

根据学长的传承,空间开40倍;

 

section (区间)

#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=2e5+10;
vector<int> v;
int root_sec[maxn];
struct node

    int l,r,sum_pos;
t[maxn*40];

int get_id(int x)

    return lower_bound(v.begin(),v.end(),x)-v.begin()+1;


int n,m,a[maxn],cnt;

void update(int l,int r,int x,int &y,int pos)

    y=++cnt;t[y]=t[x];t[y].sum_pos++;
    if(l==r) return ;
    int mid=(l+r)>>1;
    if(pos<=mid) update(l,mid,t[x].l,t[y].l,pos);
    else update(mid+1,r,t[x].r,t[y].r,pos);


int query_id(int l,int r,int x,int y,int sum_k)

    if(l==r) return l;
    int sum_sec=t[t[y].l].sum_pos-t[t[x].l].sum_pos;
    int mid=(l+r)>>1;
    if(sum_sec>=sum_k) return query_id(l,mid,t[x].l,t[y].l,sum_k);
    else return query_id(mid+1,r,t[x].r,t[y].r,sum_k-sum_sec);


int main()

    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    
        scanf("%d",&a[i]);
        v.push_back(a[i]);
    
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
    for(int i=1;i<=n;i++) update(1,n,root_sec[i-1],root_sec[i],get_id(a[i]));
    for(int i=1;i<=m;i++)
    
        int l,r,k;
        scanf("%d%d%d",&l,&r,&k);
        printf("%d\n",v[query_id(1,n,root_sec[l-1],root_sec[r],k)-1]);
    
    return 0;

 

 

 

 

 

 

至于为什么叫主席树,是因为发明他的人叫HJT;

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

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

P3701 「伪模板」主席树

Yangk's 静态主席树-模板

主席树模板

模板主席树

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