首页 > 其他分享 >可持久化数组

可持久化数组

时间:2023-03-23 16:35:15浏览次数:51  
标签:rt 持久 int mid num il 数组 cs

可持久化数组

可以写一棵可持久化线段树不过受到宇宙射线的影响,写了个奇奇怪怪的东西

因为是单点修改、单点查询,线段树只有叶子结点有用

中间结点没什么用还浪费空间,所以就不要中间结点了(大雾)

考虑建一棵树(大概类似平衡树?),维护左右儿子和权值,其他操作类似正常可持久化操作

\(build\)

奇奇怪怪的建树

il int build(cs int l,cs int r){
    ri int mid=(l+r)>>1,rt=++id;
    num[rt]=a[mid];
    if(l^mid) ls[rt]=build(l,mid-1);
    if(r^mid) rs[rt]=build(mid+1,r);
    return rt;
}

\(update\)

可持久化部分,每次增加一条链

il int add(cs int o){
    num[++id]=num[o];
    ls[id]=ls[o],rs[id]=rs[o];
    return id;
}

il void upd(int &rt,cs int k,cs int val){
    ri int l=1,r=n,mid,i=rt=add(rt);
    while(1){
        mid=(l+r)>>1;
        if(mid==k) {num[i]=val;break;}
        if(mid<k) rs[i]=add(rs[i]),l=mid+1,i=id;
        else ls[i]=add(ls[i]),r=mid-1,i=id;
    }
}

\(ask\)

il int ask(ri int rt,cs int k){
    ri int l=1,r=n,mid;
    while(1){ 
        mid=(l+r)>>1;
        if(mid==k) return num[rt];
        if(mid<k) l=mid+1,rt=rs[rt];
        else r=mid-1,rt=ls[rt];
    }
}
点击查看代码
#include <bits/stdc++.h>
#define il inline
#define cs const
#define ri register
#define F(s) freopen(#s".in","r",stdin),freopen(#s".out","w",stdout);            
using namespace std;

namespace Q{
    il int rd(){
        ri int x=0;ri bool f=0;ri char c=getchar();
        while(!isdigit(c)) f|=(c==45),c=getchar();
        while(isdigit(c)) x=x*10+(c^48),c=getchar();
        return f?-x:x;
    }
    il void wt(int x){
        if(x<0) x=-x,putchar(45);
        if(x>=10) wt(x/10);
        return putchar(x%10|48),void();
    }
    il void wn(cs int x,cs char c=10){wt(x),putchar(c);}
} using namespace Q;

cs int N=1000005,LN=21000005;
int rot[N],a[N],n,m,id;
int num[LN],ls[LN],rs[LN];

il int build(cs int l,cs int r){
    ri int mid=(l+r)>>1,rt=++id;
    num[rt]=a[mid];
    if(l^mid) ls[rt]=build(l,mid-1);
    if(r^mid) rs[rt]=build(mid+1,r);
    return rt;
}

il int add(cs int o){
    num[++id]=num[o];
    ls[id]=ls[o],rs[id]=rs[o];
    return id;
}

il void upd(int &rt,cs int k,cs int val){
    ri int l=1,r=n,mid,i=rt=add(rt);
    while(1){
        mid=(l+r)>>1;
        if(mid==k) {num[i]=val;break;}
        if(mid<k) rs[i]=add(rs[i]),l=mid+1,i=id;
        else ls[i]=add(ls[i]),r=mid-1,i=id;
    }
}

il int ask(ri int rt,cs int k){
    ri int l=1,r=n,mid;
    while(1){ 
        mid=(l+r)>>1;
        if(mid==k) return num[rt];
        if(mid<k) l=mid+1,rt=rs[rt];
        else r=mid-1,rt=ls[rt];
    }
}

signed main(){
    n=rd(),m=rd();
    for(ri int i=1;i<=n;++i) a[i]=rd();
    rot[0]=build(1,n);
    for(ri int i=1,op,k;i<=m;++i){
        rot[i]=rot[rd()],op=rd(),k=rd();
        op&1?upd(rot[i],k,rd()):wn(ask(rot[i],k));
    }
    return 0;
}

edit

标签:rt,持久,int,mid,num,il,数组,cs
From: https://www.cnblogs.com/windymoon/p/17247943.html

相关文章