和线段树类似,每个结点也要打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. git学习02 - log查看&版本回退

    1.查看更新记录 git log /  git log --pretty=oneline D:\learn\git_test>git log commit a915e7b12076673d778 ...

  2. Java设计模式--装饰器模式到Java IO 流

    装饰器模式 抽象构件角色:给出一个抽象接口,以规范准备接受附加责任的对象. 具体构件角色:定义准备接受附加责任的对象. 抽象装饰角色:持有一个构件对象的实例,并对应一个与抽象构件接口一致的接口. 具体 ...

  3. Apache的安装与配置

    apahe官网 http://www.apache.org/ 安装及配置https://blog.csdn.net/liyang4534/article/details/78036591 常见问题的处 ...

  4. 图解TCP/IP

    序言 ----

  5. mp的猜猜看

    ~~~~|yjb1072452141---dc9339b4c33103abc4919375203e7a24|A1482583628---0142e0b6090b9b2838328445a79cd1b8 ...

  6. [Reinforcement Learning] Value Function Approximation

    为什么需要值函数近似? 之前我们提到过各种计算值函数的方法,比如对于 MDP 已知的问题可以使用 Bellman 期望方程求得值函数:对于 MDP 未知的情况,可以通过 MC 以及 TD 方法来获得值 ...

  7. (七)File 文件的操作

    一.文件读写模式 1.文件的几种模式: 格式:f=open("文件名","模式",encode="utf-8") #文件的只读模式 f1=o ...

  8. python文本操作—读、写

    文本文件存储的数据有很多,我们需要把这些文本里的内容读出来,然后在浏览器上面显示. 1.读取整个文本文件 格式: with open(路径) as 变量: 变量.read() 关键字with作用:在不 ...

  9. JavaScript表单验证的相关事件

    1.  表单元素: a)         Input标签:文本框(text)—密码框(password)—单选—复选框—文件—图像—隐藏—按钮—提交—重置,表单元素都在input标签 b)       ...

  10. MySQL插入中文数据出现?号

    原文转载自:https://blog.csdn.net/LynneZoe/article/details/79174119 运行环境:win10 mysql版本:Mysql5.6 做一个项目的时候,向 ...