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

来源:互联网 发布:哲学视频讲座视频知乎 编辑:程序博客网 时间:2024/05/18 01:22

当修改线段树产生新的版本时,对于不需要修改的区间,直接指向原有的点,需要修改的区间,建立新点并连过去。 所以只需要维护m棵线段树的根,动态开点就可以了。
【模板】可持久化数组(可持久化线段树/平衡树) 洛谷P3919

#include<bits/stdc++.h>using namespace std;const int N=1e6+5;struct Node{    int val;    Node *ch[2];}*root[N];int n,m,a[N];void build(Node *&root,int L,int R){    root=new Node;    if(L==R){        root->val=a[L];        return;    }    int mid=L+R>>1;    build(root->ch[0],L,mid);    build(root->ch[1],mid+1,R);}void insert(Node* &root,int L,int R,int loc,int val){    Node *tmp=root;    root=new Node;    root->ch[0]=tmp->ch[0];    root->ch[1]=tmp->ch[1];    if(L==R)    {root->val=val;return;}    int mid=L+R>>1;    if(loc<=mid)    insert(root->ch[0],L,mid,loc,val);    else            insert(root->ch[1],mid+1,R,loc,val);}int Query(Node *root,int L,int R,int loc){    if(L==R)    return root->val;    int mid=L+R>>1;    if(loc<=mid)    return Query(root->ch[0],L,mid,loc);    else            return Query(root->ch[1],mid+1,R,loc);}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 ver,opt;        scanf("%d%d",&ver,&opt);        root[i]=root[ver];        if(opt==1){            int loc,val;            scanf("%d%d",&loc,&val);            insert(root[i],1,n,loc,val);        }        else{            int loc;            scanf("%d",&loc);            printf("%d\n",Query(root[i],1,n,loc));        }    }    return 0;}