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

#include<bits/stdc++.h>
#define ll long long
#define N 200005
#define ls(x) tr[x].s[0]
#define rs(x) tr[x].s[1]
#define mid (l+r>>1)
using namespace std;

struct node
{
    int s[2],cnt;
}tr[N*22];
int root[N],tot;
void build(int &x,int l,int r)
{
    x=++tot;
    if(l==r) return;
    build(ls(x),l,mid);
    build(rs(x),mid+1,r);
}
void Insert (int x,int &y,int l,int r,int v)
{
    y=++tot;
    tr[y]=tr[x];
    tr[y].cnt++;
    if(l==r) return;
    if(v<=mid) Insert(ls(x),ls(y),l,mid,v);
    else Insert(rs(x),rs(y),mid+1,r,v);
}
int query(int x,int y,int l,int r,int k)
{
    if(l==r) return l;
    int s=tr[ls(y)].cnt-tr[ls(x)].cnt;
    if(k<=s) return query(ls(x),ls(y),l,mid,k);
    else return query(rs(x),rs(y),mid+1,r,k-s);
}
//离散化
vector<int> v;
int n,m,a[N],vn;
void work()
{
    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());
    vn=v.size();
}
int getid(int x)
{
    return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
int main()
{
    scanf("%d%d",&n,&m);
    work();
    for(int i=1;i<=n;i++)
    {
        Insert(root[i-1],root[i],1,vn,getid(a[i]));
    }
    for(int i=1;i<=m;i++)
    {
        int l,r,k;
        scanf("%d%d%d",&l,&r,&k);
        int id=query(root[l-1],root[r],1,vn,k)-1;
        printf("%d\n",v[id]);
    }
    return 0;
}

可持久化数组

#include<bits/stdc++.h>
#define ll long long
#define N 1000005
#define ls(x) tr[x].s[0]
#define rs(x) tr[x].s[1]
#define mid (l+r>>1)
using namespace std;

struct node
{
    int s[2],v;
} tr[N*25];
int root[N],tot,a[N];
void build(int &x,int l,int r)
{
    x=++tot;
    if(l==r)
    {
        tr[x].v=a[l];
        return;
    }
    build(ls(x),l,mid);
    build(rs(x),mid+1,r);
}
void modify(int x,int &y,int l,int r,int k,int v)
{
    y=++tot;
    tr[y]=tr[x];
    if(l==r)
    {
        tr[y].v=v;
        return ;
    }
    if(k<=mid) modify(ls(x),ls(y),l,mid,k,v);
    else modify(rs(x),rs(y),mid+1,r,k,v);
}
int query(int x,int l,int r,int k)
{
    if(l==r) return tr[x].v;
    if(k<=mid) return query(ls(x),l,mid,k);
    else return query(rs(x),mid+1,r,k);
}
int n,m;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++) scanf("%d",a+i);
    build(root[0],1,n);
    for(int i=1; i<=m; i++)
    {
        int rt,op,x,y;
        scanf("%d%d%d",&rt,&op,&x);
        if(op==1)
        {
            scanf("%d",&y);
            modify(root[rt],root[i],1,n,x,y);
        }
        else
        {
            printf("%d\n",query(root[rt],1,n,x));
            root[i]=root[rt];
        }
    }
    return 0;
}

可持久化平衡树

#include<bits/stdc++.h>
#define ll long long
#define N 500005
#define ls(x) tr[x].s[0]
#define rs(x) tr[x].s[1]
using namespace std;
struct node
{
    int s[2],v,rnd,siz;
} tr[N*50];
int root[N],tot;
void newnode(int &x,int v)
{
    x = ++tot;
    tr[x].v=v;
    tr[x].rnd=rand();
    tr[x].siz=1;
}
void pushup(int p)
{
    tr[p].siz=tr[ls(p)].siz+tr[rs(p)].siz+1;
}
void split(int p,int v,int &x,int &y)
{
    if(!p)
    {
        x=y=0;
        return;
    }
    if(tr[p].v<=v)
    {
        x = ++tot;
        tr[x]=tr[p];
        split(rs(x),v,rs(x),y);
        pushup(x);
    }
    else
    {
        y = ++tot;
        tr[y]=tr[p];
        split(ls(y),v,x,ls(y));
        pushup(y);
    }
}
int Merge(int x,int y)
{
    if(!x||!y) return x+y;
    if(tr[x].rnd<tr[y].rnd)
    {
        rs(x)=Merge(rs(x),y);
        pushup(x);
        return x;
    }
    else
    {
        ls(y)=Merge(x,ls(y));
        pushup(y);
        return y;
    }
}
void Insert(int &root,int v)
{
    int x,y,z;
    split(root,v,x,y);
    newnode(z,v);
    root=Merge(Merge(x,z),y);
}
void del(int &root,int v)
{
    int x,y,z;
    split(root,v,x,z);
    split(x,v-1,x,y);
    y=Merge(ls(y),rs(y));
    root=Merge(Merge(x,y),z);
}
int getrank(int &root,int v)
{
    int x,y;
    split(root,v-1,x,y);
    int ans=tr[x].siz+1;
    root=Merge(x,y);
    return ans;
}
int getval(int root,int v)
{
    if(v==tr[ls(root)].siz+1)
        return tr[root].v;
    else if(v<=tr[ls(root)].siz)
        return getval(ls(root),v);
    else
        return getval(rs(root),v-tr[ls(root)].siz-1);
}
int getpre(int &root,int v)
{
    int x,y,s,ans;
    split(root,v-1,x,y);
    if(!x)return -2147483647;
    s=tr[x].siz;
    ans=getval(x,s);
    root=Merge(x,y);
    return ans;
}
int getnxt(int &root,int v)
{
    int x,y,ans;
    split(root,v,x,y);
    if(!y)return 2147483647;
    else ans=getval(y,1);
    root=Merge(x,y);
    return ans;
}
int main()
{
    int n,ver,op,v;
    scanf("%d",&n);
    for(int i=1; i<=n; ++i)
    {
        scanf("%d%d%d",&ver,&op,&v);
        root[i]=root[ver];
        if(op==1)Insert(root[i],v);
        else if(op==2)del(root[i],v);
        else if(op==3)printf("%d\n",getrank(root[i],v));
        else if(op==4)printf("%d\n",getval(root[i],v));
        else if(op==5)printf("%d\n",getpre(root[i],v));
        else printf("%d\n",getnxt(root[i],v));
    }
    return 0;
}