可持久化數組(線段樹)[模板題]

頹廢 QAQ 隨便亂刷題ios

話說可持久化都這麼簡單嗎?(可能可持久化並查集難一些,至於平衡樹麼….emmm非持久化板子都沒過掉還可持久化)
emmm,總這 這道題 仍是蠻簡單的git

其實這道題就沒什麼,相似我以前寫的那棵主席樹,用的思路相似,就是防止節點重複,儘可能去借用節點
只不過主席樹中根的編號是前綴編號,可持久化線段樹根的編號是歷史版本的編號罷了函數

//by Judge
#include<iostream>
#include<cstdio>
#define mid (l+r>>1)
using namespace std;
const int M=1e6+11;
inline int read() {  //壓行讀優
    int x=0,f=1; char c=getchar();
    for(; !isdigit(c); c=getchar()) if(c=='-') f=-1;
    for(; isdigit(c); c=getchar()) x=x*10+c-'0'; return x*f;
}
int n,m,cnt;
int a[M],rt[M<<5],ch[M<<5][2],val[M<<5];
void build(int& now,int l,int r) {  //建樹,和普通主席樹幾乎同樣的
    now=++cnt; if(l==r) return (void)(val[now]=a[l]);
    build(ch[now][0],l,mid), build(ch[now][1],mid+1,r);
}
void update(int& now,int las,int l,int r,int q,int v) {  //很相似,和主席樹幾乎同樣的
    now=++cnt; if(l==r) return (void)(val[now]=v);
    // 而後判斷 q 在 mid 左方或右方,左(右)兒子直接調用 las 的,右(左)兒子遞歸獲得
    if(q<=mid) ch[now][1]=ch[las][1], update(ch[now][0],ch[las][0],l,mid,q,v);
    else ch[now][0]=ch[las][0], update(ch[now][1],ch[las][1],mid+1,r,q,v);
}
int query(int now,int l,int r,int q) {  //詢問 歷史版本 now 中的節點 q ,和主席樹幾乎同樣的
    if(l==r) return val[now];
    if(q<=mid) return query(ch[now][0],l,mid,q);
    else return query(ch[now][1],mid+1,r,q);
}
int main() {  //主函數都是很是的簡潔...可持久化線段樹 50 行(壓壓行只有37)不到就能夠操過去了QAQ
    n=read(), m=read();
    for(int i=1; i<=n; ++i) a[i]=read();
    build(rt[0],1,n);
    for(int i=1,pre,opt,x,y; i<=m; ++i) {
        pre=read(),opt=read();
        if(opt==1) {
            x=read(),y=read(),
            update(rt[i],rt[pre],1,n,x,y);  //將歷史版本的信息傳遞進當前版本
        } else {
            x=read(),rt[i]=rt[pre],
            printf("%d\n",query(rt[i],1,n,x)); //將詢問版本的信息傳入當前版本後直接詢問便可
        }
    } return 0;
}
相關文章
相關標籤/搜索