可持久化线段树——区间更新hdu4348
和线段树类似,每个结点也要打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的更多相关文章
- 计蒜客 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 ...
- HDU 1556 Color the ball(线段树区间更新)
Color the ball 我真的该认真的复习一下以前没懂的知识了,今天看了一下线段树,以前只会用模板,现在看懂了之后,发现还有这么多巧妙的地方,好厉害啊 所以就应该尽量搞懂 弄明白每个知识点 [题 ...
- hihoCoder 1080 : 更为复杂的买卖房屋姿势 线段树区间更新
#1080 : 更为复杂的买卖房屋姿势 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho都是游戏迷,“模拟都市”是他们非常喜欢的一个游戏,在这个游戏里面他们 ...
- HDU 5023 A Corrupt Mayor's Performance Art(线段树区间更新)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5023 解题报告:一面墙长度为n,有N个单元,每个单元编号从1到n,墙的初始的颜色是2,一共有30种颜色 ...
- HDU 4902 Nice boat 2014杭电多校训练赛第四场F题(线段树区间更新)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4902 解题报告:输入一个序列,然后有q次操作,操作有两种,第一种是把区间 (l,r) 变成x,第二种是 ...
- HDU 1698 线段树 区间更新求和
一开始这条链子全都是1 #include<stdio.h> #include<string.h> #include<algorithm> #include<m ...
- POJ-2528 Mayor's posters (线段树区间更新+离散化)
题目分析:线段树区间更新+离散化 代码如下: # include<iostream> # include<cstdio> # include<queue> # in ...
- ZOJ 1610 Count the Colors (线段树区间更新)
题目链接 题意 : 一根木棍,长8000,然后分别在不同的区间涂上不同的颜色,问你最后能够看到多少颜色,然后每个颜色有多少段,颜色大小从头到尾输出. 思路 :线段树区间更新一下,然后标记一下,最后从头 ...
- POJ 2528 Mayor's posters (线段树区间更新+离散化)
题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值 ...
随机推荐
- 动态强制改变for循环里面item的值
var item = that.data.articles[inde_x]//获取数据列表 item.is_collection = 1//希望将特定的值改变 console.log(that.dat ...
- 【NLP】BLEU值满分是100分吗?
为了解决这个问题,首先需要知道BLEU值是如何计算出来的. BLEU全称是Bilingual Evaulation Understudy.其意思是双语评估替补.所谓Understudy(替补),意思是 ...
- 在Ubuntu 18.04系统上安装Systemback的方法(抄)
在Ubuntu 18.04系统上安装Systemback的方法 2018-12-26 21:39:05作者:林莉稿源:云网牛站 本文介绍如何在Ubuntu 18.04或者Ubuntu 18.10系统上 ...
- Wiki leaks files backup
Wiki leaks files backup 来源 http://ftp.icm.edu.pl/packages/incoming/torrent/ Index of /packages/inco ...
- 【linux】工作中linux系统常用命令操作整理
1.Linux如何查看端口 使用lsof(list open files)命令,lsof -i:端口号 用于查看某一端口的占用情况,比如查看8000端口使用情况,lsof -i:8000. 或者使用n ...
- qcow2虚拟磁盘映像转化为vmdk
qcow2虚拟磁盘映像转化为vmdk yum install qemu-img –y qemu-img info source-name.vmdk 查看虚拟机信息 qemu-img convert - ...
- Linux-Jenkins安装部署
Jenkins 安装及插件安装 Jenkins简介: Jenkins只是一个平台,真正运作的都是插件.这就是jenkins流行的原因,因为jenkins什么插件都有 Hudson是Jenkins的前身 ...
- logstash filter 处理json
根据输入的json字段,分别建立索引.循环生成注册log和登录log保存到testlog文件中,结果如下: {"method":"register"," ...
- Java Socket、计算机网络
一个服务器对应一个客户端 http://blog.51cto.com/wangdy/1588379 https://www.cnblogs.com/rocomp/p/4790340.html pack ...
- flask websocker
WebSocket 是一种网络通信协议.RFC6455 定义了它的通信标准. HTTP 协议是一种无状态的.无连接的.单向的应用层协议.它采用了请求/响应模型.通信请求只能由客户端发起,服务端对请求做 ...