题意:

给一个数组A[1] ~ A[n],有4种操作:

Q l r询问l r区间和

C l r v给l r区间每个数加v

H l r t询问第t步操作的时候l r区间和

B t返回到第t步操作

思路:

用主席树维护常规的线段树。我们之前已经知道了主席树单点更新,只要新增一条链就ok了,区间更新也有点差不多。我们每次要更新都用一个lazy标记,但是显然我们不能去更新那些已经存在的区间,那么我们就新建出所有要更新的区间。因为可持久化线段树有些结点不是自己的,所以我们不能直接简单的push up和push down,那么我们在对区间加v的时候处理为:如果这个区间完全是新建的(L <= l && R >= r),那么我直接加lazy标记就好,不是的话就直接更新要更新的区间的那部分 T[now].sum += (min(R, r) - max(L, l) + 1) * v ,然后继续往下更新。我在查询的时候,遇到lazy都要直接加上,因为我这个lazy是不往下传的,所以你往下走的时候要先加上指定的区间的lazy。

代码:

#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e5 + ;
const int M = maxn * ;
const ull seed = ;
const int INF = 0x3f3f3f3f;
const int MOD = ;
int a[maxn], root[maxn], tot;
int n, m;
struct node{
int lson, rson;
ll sum, lazy;
}T[maxn * ];
void init(){
tot = ;
}
void pushUp(int rt){
T[rt].sum = T[T[rt].lson].sum + T[T[rt].rson].sum;
}
void build(int l, int r, int &rt){
rt = ++tot;
T[rt].lazy = T[rt].sum = ;
if(l == r){
T[rt].sum = a[l];
return;
}
int m = (l + r) >> ;
build(l, m,T[rt].lson);
build(m + , r, T[rt].rson);
pushUp(rt);
}
void update(int l, int r, int L, int R, int &now, int pre, ll v){
T[++tot] = T[pre], now = tot;
T[now].sum += (min(R, r) - max(L, l) + ) * v;
if(L <= l && R >= r){
T[now].lazy += v;
return;
}
int m = (l + r) >> ;
if(L <= m)
update(l, m, L, R, T[now].lson, T[pre].lson, v);
if(R > m)
update(m + , r, L, R, T[now].rson, T[pre].rson, v);
}
ll query(int l, int r, int L, int R, int rt){
if(L <= l && R >= r){
return T[rt].sum;
}
int m = (l + r) >> ;
ll ans = (min(R, r) - max(L, l) + ) * T[rt].lazy;
if(L <= m)
ans += query(l, m, L, R, T[rt].lson);
if(R > m)
ans += query(m + , r, L, R, T[rt].rson);
return ans;
}
int main(){
while(~scanf("%d%d", &n, &m)){
init();
for(int i = ; i <= n; i++)
scanf("%d", &a[i]);
int time = ;
build(, n, root[time]);
while(m--){
char o[];
int l, r, v;
scanf("%s", o);
if(o[] == 'C'){
scanf("%d%d%d", &l, &r, &v);
++time;
update(, n, l, r, root[time], root[time - ], v);
}
else if(o[] == 'Q'){
scanf("%d%d", &l, &r);
printf("%lld\n", query(, n, l, r, root[time]));
}
else if(o[] == 'H'){
scanf("%d%d%d", &l, &r, &v);
printf("%lld\n", query(, n, l, r, root[v]));
}
else{
scanf("%d", &v);
time = v;
}
}
}
return ;
}

HDU 4348 To the moon(主席树 区间更新)题解的更多相关文章

  1. hdu 4348 To the moon (主席树区间更新)

    传送门 题意: 一个长度为n的数组,4种操作 : (1)C l r d:区间[l,r]中的数都加1,同时当前的时间戳加1 . (2)Q l r:查询当前时间戳区间[l,r]中所有数的和 . (3)H ...

  2. hdu 4348 To the moon 主席树区间更新

    To the moon Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Prob ...

  3. HDU 4348 To the moon 主席树 在线更新

    http://acm.hdu.edu.cn/showproblem.php?pid=4348 以前做的主席树没有做过在线修改的题做一下(主席树这种东西正经用法难道不是在线修改吗),标记永久化比较方便. ...

  4. hdu 4348 To the moon (主席树)

    版权声明:本文为博主原创文章,未经博主允许不得转载. hdu 4348 题意: 一个长度为n的数组,4种操作 : (1)C l r d:区间[l,r]中的数都加1,同时当前的时间戳加1 . (2)Q ...

  5. HDU 4348 To the moon 主席树

    题意: 给出一个长度为\(n(n \leq 10^5)\)的序列,最开始时间\(t=0\),支持下面几个操作: \(C \, l \, r \, d\):将区间\([l,r]\)每个数都加上\(d\) ...

  6. HDU 4348 主席树区间更新

    To the moon Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  7. HDU.1556 Color the ball (线段树 区间更新 单点查询)

    HDU.1556 Color the ball (线段树 区间更新 单点查询) 题意分析 注意一下pushdown 和 pushup 模板类的题还真不能自己套啊,手写一遍才行 代码总览 #includ ...

  8. HDU 4348 To the moon (主席树区间更新)

    题意:首先给你n个数,开始时间为0,最后按照操作输出 给你四种操作: 1. C l r d :  在(l,r)区间都加上d,时间加一2. Q l r :  询问现在(l,r)的区间和3. H l r ...

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

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

随机推荐

  1. MATLAB算术运算符和常用函数

    1 算术运算符 Matlab中的算术运算符按优先级由高到低为: (1) ^           幂 (2) *            乘      /            右除(正常除)       ...

  2. 面试 Java 高级后端开发,要准备哪些知识点?

    其实公司肯花时间让你去面试,前提条件一定是通过你的简历,一定发现了你和公司的匹配点,也就是说,一定是有录用意向的. 在技术面试的时间段里(最长1个小时),你如果能展现你的优势那是最好的,但如果你做不到 ...

  3. ValueError: Variable rnn/basic_lstm_cell/kernel already exists, disallowed. Did you mean to set reuse=True or reuse=tf.AUTO_REUSE in VarScope? Originally defined at:

    问题 ValueError: Variable rnn/basic_lstm_cell/kernel already exists, disallowed. Did you mean to set r ...

  4. Linux 常用命令,处理端口和Tomcat,mysql

    查看端口占用 1.lsof -i:端口号 2.netstat -tunlp|grep 端口号 都可以查看指定端口被哪个进程占用的情况 kill -9 进程号    强制结束进程 启动 1.使用 ser ...

  5. jquery的输入框自动补全功能+ajax

    jquery的输入框自动补全功能+ajax 2017年05月10日 18:51:39 辣姐什么鬼 阅读数:1461 标签: web前端 更多 个人分类: web前端   内容参考网友文章写成,原博的链 ...

  6. RAID技术详解

    RAID:Redundant Array of Independent Disks 中文我们称为独立冗余磁盘阵列.基本上是见名知意.RAID的基本思想就是将多个容量较小且价格实惠的磁盘进行组合起来构成 ...

  7. A Simple Nim (SG打表找规律)

    题意:有n堆石子,每次可以将其中一堆分为数量不为0的3堆,或者从其中一堆中拿走若干个,最终拿完的那个人赢. 思路:直接暴力SG状态,然后找出其中的规律,异或一下每一堆的状态就可以了. #include ...

  8. arcgis for js 根据多边形自动缩放

    交代背景:多边形已经渲染在图层上,然后根据多边形自动缩放值合适的大小: 思路:获取图层信息,获取图层中的几何信息,获取图形范围信息,在地图上设置范围:(下面的方法有封装)记一下思路就好 var pol ...

  9. html-webpack-plugin 遇到 throw new Error('Cyclic dependency' + nodeRep)

    今天遇到了 html-webpack-plugin 遇到 throw new Error('Cyclic dependency' + nodeRep) 错. 刚查到一篇文章,<手摸手,带你用合理 ...

  10. Vue入门:Vue环境安装

    安装环境 操作系统:Windows 10 64位 安装Node.js 1. 下载系统对应版本安装包 下载地址:https://nodejs.org/en/download/ 2. 安装 除安装地址外其 ...