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

//主席树 可持久化线段树 
//对于每次更新新建根节点
//将涉及到改变的节点全部新建,未涉及改变的节点全部用以前的节点代替
//可大大节省空间 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
int n,m,cnt,root[1000001],a[1000001];
struct uio{
    int num,ls,rs;
}tree[20000001];
void build(int l,int r,int &now)
{
    now=++cnt;
    if(l==r)
    {
        tree[now].num=a[l];
        return;
    }
    int mid=(l+r)/2;
    build(l,mid,tree[now].ls);
    build(mid+1,r,tree[now].rs);
}
void update(int l,int r,int pos,int k,int &now,int last)//左右儿子,修改位置下标,修改值,新建版本root,查询版本root 
{
    now=++cnt;
    tree[now]=tree[last];
    if(l==r)
    {
        tree[now].num=k;
        return;
     }
     int mid=(l+r)/2;
     if(pos<=mid)
         update(l,mid,pos,k,tree[now].ls,tree[last].ls);
    else update(mid+1,r,pos,k,tree[now].rs,tree[last].rs);
}
int query(int l,int r,int pos,int last)
{
    if(l==r)
        return tree[last].num;
    int mid=(l+r)/2;
    if(pos<=mid)
        return query(l,mid,pos,tree[last].ls);
    else return query(mid+1,r,pos,tree[last].rs);
}
void do_something()
{
    for(int i=1;i<=m;i++)
    {
        int u,k,v,w;
        scanf("%d%d",&u,&k);
        if(k==1)
        {
            scanf("%d%d",&v,&w);
            update(1,n,v,w,root[i],root[u]);
        }
        else
        {
            scanf("%d",&v);
            printf("%d\n",query(1,n,v,root[u]));
            root[i]=root[u];
        }
    } 
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    build(1,n,root[0]);
    do_something();
     return 0;
}

猜你喜欢

转载自www.cnblogs.com/water-radish/p/9280886.html