可持久化线段树——区间更新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块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值 ...
随机推荐
- nginx--default_server定义规则及配置
nginx 的 default_server 指令可以定义默认的 server 出处理一些没有成功匹配 server_name 的请求,如果没有显式定义,则会选取第一个定义的 server 作为 de ...
- Python 库/模块的安装、查看
关于如何查看本地python类库详细信息的方法 关于如何查看本地python类库详细信息的方法 - 小白裸奔 - CSDN博客 python -m pydoc -p 1234 help('module ...
- python3.7安装pylint
python3.7安装pylint之"setuptools"版本错误 借鉴:错题集(已解决):pyinstaller报错ModuleNotFoundError: No module ...
- 「快速傅里叶变换(FFT)」学习笔记
FFT即快速傅里叶变换,离散傅里叶变换及其逆变换的快速算法.在OI中用来优化多项式乘法. 本文主要目的是便于自己整理.复习 FFT的算法思路 已知两个多项式的系数表达式,要求其卷积的系数表达式. 先将 ...
- adb bat 执行滑动事件
chcp 65001 @echo off echo 开始滑动 set str =0 :start adb shell input swipe 100 150 100 100 choice /t 1 / ...
- BZOJ 3000: Big Number (数学)
题目: https://www.lydsy.com/JudgeOnline/problem.php?id=3000 题解: 首先n很大,O(n)跑不过,那么就要用一些高端 而且没听过 的东西——sti ...
- mac-redis安装与使用
安装: brew install redis --------------- 使用: 启动redis-server: sudo redis-server 连接:./redis-cli -h 127.0 ...
- hive字段名、注释中文显示问号
问题如下图: 解决方法: header1的/etc/my.conf文件,在[mysqld]分组下面添加配置:character-set-server=utf8init_connect='SET NAM ...
- ./runInstaller: Permission denied
一:问题描述 安装oracle过程中出现 二:解决 /usr/local/Oracle11./database/runInstaller /usr/local/Oracle11./database/i ...
- SimMechanics/Second Generation倒立摆模型建立及初步仿真学习
笔者最近捣鼓Simulink,发现MATLAB的仿真模块真的十分强大,以前只是在命令窗口敲点代码,直到不小心敲入simulink,就一发不可收拾.话说simulink的模块化建模确实方便,只要拖拽框框 ...