和线段树类似,每个结点也要打lazy标记

但是lazy标记和线段树不一样

具体区别在于可持久化后lazy-tag不用往下传递,而是固定在这个区间并不断累加,变成了这个区间固有的性质(有点像分块的标记了)

update就按照这么来

int update(int last,int L,int R,int c,int l,int r){
int now=++size;
T[now]=T[last]; if(L<=l && R>=r){
T[now].sum+=(r-l+)*c;
T[now].add+=c;
return now;
} int mid=l+r>>;
if(L<=mid)T[now].lc=update(T[last].lc,L,R,c,l,mid);
if(R>mid)T[now].rc=update(T[last].rc,L,R,c,mid+,r);
pushup(l,r,now);
return now;
}

查询时由于lazytag固定在区间上。所以向下查询的时候要把上层的lazytag的影响都算上,即递归时传递一个上层区间的  影响值(例如add)

ll query(int now,int L,int R,int add,int l,int r){
if(L<=l && R>=r) return T[now].sum+(ll)add*(r-l+);
int mid=l+r>>;
ll res=;add+=T[now].add;
if(L<=mid)res+=query(T[now].lc,L,R,add,l,mid);
if(R>mid)res+=query(T[now].rc,L,R,add,mid+,r);
return res;
}

此外还有合并维护时,由于子区间没有收到父区间的影响,所以合并时还要算父区间的lazytag

void pushup(int l,int r,int rt){T[rt].sum=T[T[rt].lc].sum+T[T[rt].rc].sum+T[rt].add*(r-l+);}

最后是完整代码,其实本题版本回滚时还可以吧size往回滚,以此节省内存

/*
主席树区间更新
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxn 100005
ll n,m,a[maxn];
struct Node{int lc,rc;ll sum,add;}T[maxn*];
int size,rt[maxn];
void pushup(int l,int r,int rt){T[rt].sum=T[T[rt].lc].sum+T[T[rt].rc].sum+T[rt].add*(r-l+);}
int build(int l,int r){
int now=++size;
if(l==r){
T[now].lc=T[now].rc=;
T[now].sum=a[l];
return now;
}
int mid=l+r>>;
T[now].lc=build(l,mid);
T[now].rc=build(mid+,r);
pushup(l,r,now);
return now;
}
int update(int last,int L,int R,int c,int l,int r){
int now=++size;
T[now]=T[last]; if(L<=l && R>=r){
T[now].sum+=(r-l+)*c;
T[now].add+=c;
return now;
} int mid=l+r>>;
if(L<=mid)T[now].lc=update(T[last].lc,L,R,c,l,mid);
if(R>mid)T[now].rc=update(T[last].rc,L,R,c,mid+,r);
pushup(l,r,now);
return now;
}
ll query(int now,int L,int R,int add,int l,int r){
if(L<=l && R>=r) return T[now].sum+(ll)add*(r-l+);
int mid=l+r>>;
ll res=;add+=T[now].add;
if(L<=mid)res+=query(T[now].lc,L,R,add,l,mid);
if(R>mid)res+=query(T[now].rc,L,R,add,mid+,r);
return res;
}
void init(){
size=;
memset(rt,,sizeof rt);
memset(T,,sizeof T);
}
int main(){
while(scanf("%lld%lld",&n,&m)==){
init();
for(int i=;i<=n;i++)scanf("%lld",&a[i]); int cur=,l,r,c;char op[];
rt[cur]=build(,n);
while(m--){
scanf("%s",op);
if(op[]=='C'){scanf("%d%d%d",&l,&r,&c);rt[++cur]=update(rt[cur-],l,r,c,,n);}
if(op[]=='Q'){scanf("%d%d",&l,&r);cout<<query(rt[cur],l,r,,,n)<<'\n';}
if(op[]=='H'){
scanf("%d%d%d",&l,&r,&c);
cout<<query(rt[c],l,r,,,n)<<'\n';
}
if(op[]=='B'){scanf("%d",&c);cur=c;}
}
// puts("");
}
}

可持久化线段树——区间更新hdu4348的更多相关文章

  1. 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)

    Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...

  2. HDU 1556 Color the ball(线段树区间更新)

    Color the ball 我真的该认真的复习一下以前没懂的知识了,今天看了一下线段树,以前只会用模板,现在看懂了之后,发现还有这么多巧妙的地方,好厉害啊 所以就应该尽量搞懂 弄明白每个知识点 [题 ...

  3. hihoCoder 1080 : 更为复杂的买卖房屋姿势 线段树区间更新

    #1080 : 更为复杂的买卖房屋姿势 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho都是游戏迷,“模拟都市”是他们非常喜欢的一个游戏,在这个游戏里面他们 ...

  4. HDU 5023 A Corrupt Mayor's Performance Art(线段树区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5023 解题报告:一面墙长度为n,有N个单元,每个单元编号从1到n,墙的初始的颜色是2,一共有30种颜色 ...

  5. HDU 4902 Nice boat 2014杭电多校训练赛第四场F题(线段树区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4902 解题报告:输入一个序列,然后有q次操作,操作有两种,第一种是把区间 (l,r) 变成x,第二种是 ...

  6. HDU 1698 线段树 区间更新求和

    一开始这条链子全都是1 #include<stdio.h> #include<string.h> #include<algorithm> #include<m ...

  7. POJ-2528 Mayor's posters (线段树区间更新+离散化)

    题目分析:线段树区间更新+离散化 代码如下: # include<iostream> # include<cstdio> # include<queue> # in ...

  8. ZOJ 1610 Count the Colors (线段树区间更新)

    题目链接 题意 : 一根木棍,长8000,然后分别在不同的区间涂上不同的颜色,问你最后能够看到多少颜色,然后每个颜色有多少段,颜色大小从头到尾输出. 思路 :线段树区间更新一下,然后标记一下,最后从头 ...

  9. POJ 2528 Mayor's posters (线段树区间更新+离散化)

    题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值 ...

随机推荐

  1. leanote使用本地账户时,去掉待同步的小红点

    切换开发者工具,如下图,点击左上角的箭头图标,选取元素,直接选择小红点. 然后会看到小红点来自于resources/app/public/themes/default.css文件中2092行: .it ...

  2. python学习日记(正则表达式)

    定义 正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配. Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式. re 模块使 Pyth ...

  3. BackGround

  4. [NOI2017]泳池

    题目描述 有一个长为\(n\),高为1001的网格,每个格子有\(p\)的概率为1,\((1-p)\)的概率0,定义一个网格的价值为极大的全一矩形,且这个矩形的底要贴着网格的底,求这个网格的价值为\( ...

  5. Floyd-蒟蒻也能看懂的弗洛伊德算法(当然我是蒟蒻)

    今天来讲点图论的知识,来看看最短路径的一个求法(所有的求法我以后会写,也有可能咕咕咕) 你们都说图看着没意思不好看,那今天就来点情景             暑假,_GC准备去一些城市旅游.有些城市之 ...

  6. Spring项目使用Junit4测试配置

    我们经常要写junit测试,在不启动整个web项目的情况下,测试自己的service实现或者是dao实现,我们来充分利用下junit4的强大功能. 1.junit4的测试类 import java.u ...

  7. Linux中errno的含义

    /****************************获取错误代码描述**************/ #include <string.h>#include <errno.h&g ...

  8. 074、如何安装和配置Rex-Ray?(2019-04-19 周五)

    参考https://www.cnblogs.com/CloudMan6/p/7607705.html   Rax-Ray 是一个优秀的Docker volume driver ,本节将学习其安装和配置 ...

  9. mockplus 原型设计工具

    国产原型工具 http://www.mockplus.cn, 该工具功能很棒. 每次打开软件都需先登陆, 好在项目文件是可以保存到本地, 可以注册为免费版/个人版/团队版/企业版. 我是免费账号, 功 ...

  10. java多线程基础篇第一篇

    1.在开始多线程之前,我们先来聊聊计算机的缓存 计算机处理一个程序需要cpu处理器与存储设备的交互.但是在计算机发展的过程中,cpu处理器的处理速度不断提高,而存储设备的读写速度却没有得到与cpu同样 ...