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

主席树留坑

可持久化权值线段树:

区间第k小数

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<map>
#include<bitset>
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dwn(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
typedef long long ll;
const int N=200000;
int n,m,cnt,tot=0;
int a[N+10],b[N+10],rt[N+10];
int sum[100*N+10],tl[100*N+10],tr[100*N+10];
int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=(x<<3)+(x<<1)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
int build(int l,int r)
{
    int t=++tot;
    sum[tot]=0;
    if(l<r)
    {
        int mid=(l+r)>>1;
        tl[t]=build(l,mid);
        tr[t]=build(mid+1,r);
    }
    return t;
}
int update(int pre,int l,int r,int x)
{
    int t=++tot;
    tl[t]=tl[pre];tr[t]=tr[pre];sum[t]=sum[pre]+1;
    if(l<r)
    {
        int mid=(l+r)>>1;
        if(x<=mid) tl[t]=update(tl[pre],l,mid,x);
        else tr[t]=update(tr[pre],mid+1,r,x);
    }
    return t;
}
int ask_sum(int u,int v,int l,int r,int k)
{
    if(l>=r) return l;
    int x=sum[tl[v]]-sum[tl[u]];
    int mid=(l+r)>>1;
    if(k<=x) return ask_sum(tl[u],tl[v],l,mid,k);
    else return ask_sum(tr[u],tr[v],mid+1,r,k-x);
}
int main()
{
    n=read(),m=read();
    rep(i,1,n)
    {
        a[i]=b[i]=read();
    }
    sort(b+1,b+n+1);
    cnt=unique(b+1,b+n+1)-b-1;
    rt[0]=build(1,cnt);
    rep(i,1,n)
    {
        int t=lower_bound(b+1,b+cnt+1,a[i])-b;
        rt[i]=update(rt[i-1],1,cnt,t);
    }
    rep(i,1,m)
    {
        int l=read(),r=read(),k=read();
        printf("%d
",b[ask_sum(rt[l-1],rt[r],1,cnt,k)]);
    }
    return 0;
}

可持久化数组-线段树实现:

可持久化数组

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<map>
#include<bitset>
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dwn(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
typedef long long ll;
const int N=1000000;
int n,m,a[N+10],rt[N+10],val[40*N+10],tl[40*N+10],tr[40*N+10],cnt=0,tot=0;
int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=(x<<3)+(x<<1)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
int build(int l,int r)
{
    int t=++tot;
    if(l==r)
    {
        val[t]=a[l];
        return t;
    }
    int mid=(l+r)>>1;
    tl[t]=build(l,mid);
    tr[t]=build(mid+1,r);
    return t;
}
int update(int pre,int l,int r,int x,int d)
{
    int t=++tot;
    if(l==r)
    {
        val[t]=d;
        return t;
    }
    tl[t]=tl[pre],tr[t]=tr[pre];
    int mid=(l+r)>>1;
    if(x<=mid) tl[t]=update(tl[pre],l,mid,x,d);
    else tr[t]=update(tr[pre],mid+1,r,x,d);
    return t;
}
int ask_val(int t,int l,int r,int x)
{
    if(l==r) return val[t];
    int mid=(l+r)>>1;
    if(x<=mid) return ask_val(tl[t],l,mid,x);
    else return ask_val(tr[t],mid+1,r,x);
}
int main()
{
    n=read(),m=read();
    rep(i,1,n) a[i]=read();
    rt[0]=build(1,n);
    rep(i,1,m)
    {
        int t=read(),opt=read(),x=read();
        if(opt==1) {int d=read();rt[++cnt]=update(rt[t],1,n,x,d);}
        if(opt==2) {printf("%d
",ask_val(rt[t],1,n,x));rt[++cnt]=rt[t];}
    }
    return 0;
}
原文地址:https://www.cnblogs.com/MYsBlogs/p/11379844.html