可持久化數組

題目背景

UPDATE : 最後一個點時間空間已經放大html

標題即題意node

有了可持久化數組,即可以實現不少衍生的可持久化功能(例如:可持久化並查集)數組

題目描述

如題,你須要維護這樣的一個長度爲 NN 的數組,支持以下幾種操做ui

  1. 在某個歷史版本上修改某一個位置上的值spa

  2. 訪問某個歷史版本上的某一位置的值

此外,每進行一次操做(對於操做2,即爲生成一個徹底同樣的版本,不做任何改動),就會生成一個新的版本。版本編號即爲當前操做的編號(從1開始編號,版本0表示初始狀態數組)code

輸入輸出格式

輸入格式:htm

 

輸入的第一行包含兩個正整數 N, MN,M, 分別表示數組的長度和操做的個數。blog

第二行包含NN個整數,依次爲初始狀態下數組各位的值(依次爲 a_iai1 \leq i \leq N1iN)。get

接下來MM行每行包含3或4個整數,表明兩種操做之一(ii爲基於的歷史版本號):it

  1. 對於操做1,格式爲v_i \ 1 \ {loc}_i \ {value}_ivi 1 loci valuei,即爲在版本v_ivi的基礎上,將 a_{{loc}_i}aloci 修改成 {value}_ivaluei

  2. 對於操做2,格式爲v_i \ 2 \ {loc}_ivi 2 loci,即訪問版本v_ivi中的 a_{{loc}_i}aloci的值

 

輸出格式:

 

輸出包含若干行,依次爲每一個操做2的結果。

 

輸入輸出樣例

輸入樣例#1: 
5 10
59 46 14 87 41
0 2 1
0 1 1 14
0 1 1 57
0 1 1 88
4 2 4
0 2 5
0 2 4
4 2 1
2 2 2
1 1 5 91
輸出樣例#1: 
59
87
41
87
88
46

說明

數據規模:

對於30%的數據:1 \leq N, M \leq {10}^31N,M103

對於50%的數據:1 \leq N, M \leq {10}^41N,M104

對於70%的數據:1 \leq N, M \leq {10}^51N,M105

對於100%的數據:1 \leq N, M \leq {10}^6, 1 \leq {loc}_i \leq N, 0 \leq v_i < i, -{10}^9 \leq a_i, {value}_i \leq {10}^91N,M106,1lociN,0vi<i,109ai,valuei109

 

代碼

思路1:樹上dfs離線操做

#include<cstdio>
#define f(c)   for(int i=1;i<=c;i++)
using namespace std;
const int maxn = 1000009;
int head[maxn],n,m,cnt,a[maxn],ans[maxn];
struct edg{int next,to;}e[maxn];
struct node{int ver,opt,pos,val;}q[maxn]; 
bool uuz[maxn];
int I(){int x=0,f=1;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;'0'<=ch&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);return x*f;}
void add(int x,int y){e[++cnt].next=head[x];head[x]=cnt;e[cnt].to=y;}
void dfs(int x){int last;
    q[x].opt==1?last=a[q[x].pos],a[q[x].pos]=q[x].val:ans[x]=a[q[x].pos];
    for(int i=head[x];i;i=e[i].next)dfs(e[i].to);
    if(q[x].opt==1)a[q[x].pos]=last;}
int main(){n=I();m=I();f(n)a[i]=I();
    f(m){q[i].ver=I();q[i].opt=I();q[i].pos=I();
        q[i].opt==1?q[i].val=I():uuz[i]=1;add(q[i].ver,i);}
    dfs(0);f(m)if(uuz[i])printf("%d\n",ans[i]);return 0;}

思路2:可持久化線段樹

#include<cstdio>
#define f(a)  for(int i=1;i<=a;i++)
const int N=1000005;
using namespace std;
int a[N],n,q,rt[N*20];
int I(){int x=0,f=1;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;'0'<=ch&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);return x*f;}
struct Persistable_Segment_Tree{
    int lc[N*20],rc[N*20],val[N*20],cnt;
    inline void build(int &o,int l,int r){
        o=++cnt;if(l==r){val[o]=a[l];return;}
        int mid=(l+r)>>1;build(lc[o],l,mid);build(rc[o],mid+1,r);}
    inline void ins(int &o,int pre,int l,int r,int q,int v){
        o=++cnt;lc[o]=lc[pre];rc[o]=rc[pre];val[o]=val[pre];
        if(l==r){val[o]=v;return;}int mid=(l+r)>>1;
        q<=mid?ins(lc[o],lc[pre],l,mid,q,v):ins(rc[o],rc[pre],mid+1,r,q,v);}
    inline int query(int o,int l,int r,int q){
        if(l==r)return val[o];int mid=(l+r)>>1;
        if(q<=mid)return query(lc[o],l,mid,q);
        else return query(rc[o],mid+1,r,q);}
}T;
int main(){n=I();int m=I();f(n)a[i]=I();T.build(rt[0],1,n);
    f(m){int pre=I(),opt=I(),x=I();
        if(opt==1){int v=I();T.ins(rt[i],rt[pre],1,n,x,v);}
       else printf("%d\n",T.query(rt[pre],1,n,x)),rt[i]=rt[pre];}
}

 思路3:主席樹

#include<cstdio>
using namespace std;
#define MAX 1000100
#define f(c)   for(int i=1;i<=c;i++)
int I(){int x=0,f=1;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;'0'<=ch&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);return x*f;}
int root[MAX],a[MAX],N,M;
struct Node{int l,r,ls,rs,val;}t[MAX*20];
int sum=0,tot=1;
void Build(int now,int l,int r){t[now].l=l;t[now].r=r;
    if(l==r){t[now].val=a[l];return;}
    t[now].ls=++tot;int mid=(l+r)>>1;
    Build(tot,l,mid);t[now].rs=++tot;Build(tot,mid+1,r);}
void AddNode(int now,int New,int k,int w){t[New]=t[now];
    if(t[now].l==t[now].r){t[New].val=w;return;}
    int mid=(t[now].l+t[now].r)>>1;
    if(k<=mid)t[New].ls=++tot,AddNode(t[now].ls,tot,k,w);
    else t[New].rs=++tot,AddNode(t[now].rs,tot,k,w);}
void Query(int now,int k){
    if(t[now].l==t[now].r){printf("%d\n",t[now].val);return;}
    int mid=(t[now].l+t[now].r)>>1;
    k<=mid?Query(t[now].ls,k):Query(t[now].rs,k);}
int main(){N=I();M=I();f(N)a[i]=I();
    Build(1,1,N);root[0]=1;
    f(M){int v=I(),opt=I();
        if(opt==1){int vv=I(),ww=I();AddNode(root[v],root[++sum]=++tot,vv,ww);}
        else{int vv=I();Query(root[v],vv);root[++sum]=root[v];}}return 0;}
相關文章
相關標籤/搜索