可持久化数组(主席树)

模板代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define mid ((l+r)>>1)
const int INF=1e9+7,MAXNODE=24e6+7,MAXN=1e6+7;
int N,M,tmp[MAXN],rt[MAXN];
int val[MAXNODE],lson[MAXNODE],rson[MAXNODE],sz;
void init(int &x,int l,int r){
    x=++sz;
    if(l==r){
        val[x]=tmp[l];
        return;
    }
    init(lson[x],l,mid);
    init(rson[x],mid+1,r);
}
void modify(int &x,int l,int r,int p,int q,int v){
    x=++sz;
    if(l==r){
        val[x]=v;
        return;
    }
    lson[x]=lson[p];
    rson[x]=rson[p];
    val[x]=val[p];
    if(q<=mid)
        modify(lson[x],l,mid,lson[p],q,v);
    else
        modify(rson[x],mid+1,r,rson[p],q,v);
}
int query(int x,int l,int r,int q){
    if(l==r)
        return val[x];
    if(q<=mid)
        return query(lson[x],l,mid,q);
    return query(rson[x],mid+1,r,q);
}
int main(){
    scanf("%d%d",&N,&M);
    for(int i=1;i<=N;i++)
        scanf("%d",tmp+i);
    init(rt[0],1,N);
    for(int i=1;i<=M;i++){
        int edit/*edition*/,oper,loc/*location*/,v/*value*/;
        scanf("%d%d%d",&edit,&oper,&loc);
        if(oper==1){
            scanf("%d",&v);
            modify(rt[i],1,N,rt[edit],loc,v);
        }else{
            printf("%d\n",query(rt[edit],1,N,loc));
            rt[i]=rt[edit];
        }
    }
    return 0;
}
View Code

原题链接题面:

  

 

 

 可持久化数组实现

 1.结构主席树

 2.思想:对于每一个版本的数组建一棵线段树,因为相邻版本差异为一个数字,所以单次修改时间空间复杂度均为O(logN)

 3.实现

  • 先定义一些数组(主席树的常规成员):
  1. const int MAXN数字个数,MAXNODE节点个数(2*N+NlogN)
    int N数字个数,M查询个数,tmp[MAXN]读入数值暂存数组,rt[MAXN]每个版本的线段树的根;
    int val[MAXNODE]线段树值,lson[MAXNODE]左儿子,rson[MAXNODE]右儿子,sz节点栈顶;
  • 初始化
  1. 读入并建树,将版本为0的线段树为初始树根
  2. scanf("%d%d",&N,&M);
    for(int i=1;i<=N;i++)
        scanf("%d",tmp+i);
    init(rt[0],1,N);

     按照动态开点线段树常规方法建树

    void init(int &x,int l,int r){
        x=++sz;
        if(l==r){
            val[x]=tmp[l];
            return;
        }
        init(lson[x],l,mid);
        init(rson[x],mid+1,r);
    }
  • 更新
  • void modify(int &x当前节点下标,int l,int r,int p上一个版本,int q要赋值的位置,int v值){
        x=++sz;
        if(l==r){找到节点,赋值并退出
            val[x]=v;
            return;
        }
        lson[x]=lson[p];复制上一个版本的节点信息
        rson[x]=rson[p];
        val[x]=val[p];
        if(q<=mid)按照动态开点线段树遍历
            modify(lson[x],l,mid,lson[p],q,v);
        else
            modify(rson[x],mid+1,r,rson[p],q,v);
    }
  • 查询:常规线段树查询
  • int query(int x当前点下标,int l,int r,int q查询位置){
        if(l==r)
            return val[x];
        if(q<=mid)
            return query(lson[x],l,mid,q);
        return query(rson[x],mid+1,r,q);
    }

 完整代码: 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 #define mid ((l+r)>>1)
 5 const int INF=1e9+7,MAXNODE=24e6+7,MAXN=1e6+7;
 6 int N,M,tmp[MAXN],rt[MAXN];
 7 int val[MAXNODE],lson[MAXNODE],rson[MAXNODE],sz;
 8 void init(int &x,int l,int r){
 9     x=++sz;
10     if(l==r){
11         val[x]=tmp[l];
12         return;
13     }
14     init(lson[x],l,mid);
15     init(rson[x],mid+1,r);
16 }
17 void modify(int &x,int l,int r,int p,int q,int v){
18     x=++sz;
19     if(l==r){
20         val[x]=v;
21         return;
22     }
23     lson[x]=lson[p];
24     rson[x]=rson[p];
25     val[x]=val[p];
26     if(q<=mid)
27         modify(lson[x],l,mid,lson[p],q,v);
28     else
29         modify(rson[x],mid+1,r,rson[p],q,v);
30 }
31 int query(int x,int l,int r,int q){
32     if(l==r)
33         return val[x];
34     if(q<=mid)
35         return query(lson[x],l,mid,q);
36     return query(rson[x],mid+1,r,q);
37 }
38 int main(){
39     scanf("%d%d",&N,&M);
40     for(int i=1;i<=N;i++)
41         scanf("%d",tmp+i);
42     init(rt[0],1,N);
43     for(int i=1;i<=M;i++){
44         int edit/*edition*/,oper,loc/*location*/,v/*value*/;
45         scanf("%d%d%d",&edit,&oper,&loc);
46         if(oper==1){
47             scanf("%d",&v);
48             modify(rt[i],1,N,rt[edit],loc,v);
49         }else{
50             printf("%d\n",query(rt[edit],1,N,loc));
51             rt[i]=rt[edit];
52         }
53     }
54     return 0;
55 }
View Code

猜你喜欢

转载自www.cnblogs.com/guoshaoyang/p/10924416.html