可持久化线段树

每次进行单点修改后,会新增\(log\ n\)个新节点,即每次更改的结点数为树的高度

增加的非叶子结点一个儿子是其他版本的节点,另一个儿子是连向新节点

空间复杂度为\(O(n+m\ log\ n)\)

\(code\)

void build(int L,int R,int &cur)
{
	cur=++tree_cnt;
	if(L==R)
	{
		val[cur]=a[L];
		return;
	}
	int mid=(L+R)>>1;
	build(L,mid,ls[cur]);
	build(mid+1,R,rs[cur]);
}
void modify(int L,int R,int pos,int v,int pre,int &cur)
{
	cur=++tree_cnt;
	ls[cur]=ls[pre],rs[cur]=rs[pre];
	val[cur]=val[pre];
	if(L==R)
	{
		val[cur]=v;
		return;
	}
	int mid=(L+R)>>1;
	if(pos<=mid) modify(L,mid,pos,v,ls[pre],ls[cur]);
	if(pos>mid) modify(mid+1,R,pos,v,rs[pre],rs[cur]);
}
int query(int L,int R,int pos,int cur)
{
	if(L==R) return val[cur];
	int mid=(L+R)>>1;
	if(pos<=mid) return query(L,mid,pos,ls[cur]);
	if(pos>mid) return query(mid+1,R,pos,rs[cur]);
}

标记永久化实现区间加区间查询

\(code:\)

void modify(int L,int R,int l,int r,ll v,int &cur)
{
    int x=++tree_cnt;
    ls[x]=ls[cur],rs[x]=rs[cur],add[x]=add[cur];
    sum[x]=sum[cur]+v*(min(R,r)-max(L,l)+1),cur=x;
    if(L<=l&&R>=r)
    {
        add[cur]+=v;
        return;
    }
    if(L<=mid) modify(L,R,l,mid,v,ls[cur]);
    if(R>mid) modify(L,R,mid+1,r,v,rs[cur]);
}
ll query(int L,int R,int l,int r,int cur)
{
    if(L<=l&&R>=r) return sum[cur];
    ll ans=add[cur]*(min(R,r)-max(L,l)+1);
    if(L<=mid) ans+=query(L,R,l,mid,ls[cur]);
    if(R>mid) ans+=query(L,R,mid+1,r,rs[cur]);
    return ans;
}
posted @ 2020-01-22 20:23  lhm_liu  阅读(173)  评论(0编辑  收藏  举报