hdu 4348 To the moon (主席树 区间更新)
链接: http://acm.hdu.edu.cn/showproblem.php?pid=4348
题意:
4种操作:
C l r c 区间[l,r]加c,时间+1
Q l r 询问当前时间区间[l,r]的和
H l r c 询问在时间t时,区间[l,r]的和
B x 回到时间x
思路:
涉及历史版本的询问,很容易想到主席树,然后尝试用线段树的思路用主席树写了下,疯狂WA,TLE,后面看了下其他人的博客。。。。发现不能加pushdown操作,因为一般来说pushdown更新完当前点后会向下更新子树,这样会新增很多点,其实我们可以将向下更新子树的操作省略,每次从根节点向下到需要的区间的过程中加上经过的点的lazy值就好了这样就实现了向下更新,且不会建过多的点。
还有因为计算从根到所求区间过程经过的标记数组对所求区间值的影响我们写法是:lazy*(R-L+1)所以查询操作没有用完全版线段树那种写法,换了一种,之前的写法,L,R,是不变的,但是我们是需要通过改变L,R,来表示当前标记数组作用的区间,需要改变L,R。
表达能力好弱啊。。。感觉讲不清楚想表达的思路。。。。难受
实现代码:、
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int M = 1e5+;
ll a[M],sum[M*],lazy[M*];
int ls[M*],rs[M*],root[M],idx;
void pushup(int l,int r,int rt){
sum[rt] = sum[ls[rt]] + sum[rs[rt]] + 1LL*(r-l+)*lazy[rt];
} void build(int l,int r,int &rt){
rt = ++idx;lazy[rt] = ; sum[rt] = ;
if(l == r){
sum[rt] = a[l];
return ;
}
int m = (l + r) >> ;
build(l,m,ls[rt]);
build(m+,r,rs[rt]);
pushup(l,r,rt);
} void update(int old,int &rt,int L,int R,ll c,int l,int r){
rt = ++idx; ls[rt] = ls[old]; rs[rt] = rs[old];
sum[rt] = sum[old]; lazy[rt] = lazy[old];
if(L <= l&&R >= r){
sum[rt] += 1LL*(r-l+)*c;
lazy[rt] += c;
return ;
}
int m = (l + r) >> ;
if(L <= m) update(ls[old],ls[rt],L,R,c,l,m);
if(R > m) update(rs[old],rs[rt],L,R,c,m+,r);
pushup(l,r,rt);
} ll query(int L,int R,int l,int r,int rt){
if(L <= l&&R >= r) return sum[rt];
int m = (l + r) >> ;
ll ans = 1LL*(R-L+)*lazy[rt];
/* 这种写法是不对的
if(L <= m) ans += query(L,R,l,m,ls[rt]);
if(R > m) ans += query(L,R,m+1,r,rs[rt]);
*/
//正确写法
if(R <= m) ans += query(L,R,l,m,ls[rt]);
else if(L > m) ans += query(L,R,m+,r,rs[rt]);
else{
ans += query(L,m,l,m,ls[rt]);
ans += query(m+,R,m+,r,rs[rt]);
}
return ans;
} char op[];
int main()
{
int n,q,x,y;
ll z;
while(scanf("%d%d",&n,&q)!=EOF){
idx = ;memset(root,,sizeof(root));
for(int i = ;i <= n;i ++)
scanf("%lld",&a[i]);
build(,n,root[]);
int tim = ;
for(int i = ;i <= q;i ++){
scanf("%s",op);
if(op[] == 'C'){
scanf("%d%d%lld",&x,&y,&z);
update(root[tim],root[tim+],x,y,z,,n);
tim++;
}
else if(op[] == 'Q'){
scanf("%d%d",&x,&y);
printf("%lld\n",query(x,y,,n,root[tim]));
}
else if(op[] == 'H'){
int t;
scanf("%d%d%d",&x,&y,&t);
printf("%lld\n",query(x,y,,n,root[t]));
}
else if(op[] == 'B'){
scanf("%d",&x);
tim = x;
}
}
}
return ;
}
hdu 4348 To the moon (主席树 区间更新)的更多相关文章
- hdu 4348 To the moon (主席树区间更新)
传送门 题意: 一个长度为n的数组,4种操作 : (1)C l r d:区间[l,r]中的数都加1,同时当前的时间戳加1 . (2)Q l r:查询当前时间戳区间[l,r]中所有数的和 . (3)H ...
- hdu 4348 To the moon 主席树区间更新
To the moon Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Prob ...
- HDU 4348 To the moon 主席树 在线更新
http://acm.hdu.edu.cn/showproblem.php?pid=4348 以前做的主席树没有做过在线修改的题做一下(主席树这种东西正经用法难道不是在线修改吗),标记永久化比较方便. ...
- hdu 4348 To the moon (主席树)
版权声明:本文为博主原创文章,未经博主允许不得转载. hdu 4348 题意: 一个长度为n的数组,4种操作 : (1)C l r d:区间[l,r]中的数都加1,同时当前的时间戳加1 . (2)Q ...
- HDU 4348 To the moon 主席树
题意: 给出一个长度为\(n(n \leq 10^5)\)的序列,最开始时间\(t=0\),支持下面几个操作: \(C \, l \, r \, d\):将区间\([l,r]\)每个数都加上\(d\) ...
- HDU 4348 主席树区间更新
To the moon Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total ...
- HDU.1556 Color the ball (线段树 区间更新 单点查询)
HDU.1556 Color the ball (线段树 区间更新 单点查询) 题意分析 注意一下pushdown 和 pushup 模板类的题还真不能自己套啊,手写一遍才行 代码总览 #includ ...
- HDU 4348 To the moon(主席树 区间更新)题解
题意: 给一个数组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步操作 思路: ...
- 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 ...
- HDU 1556 Color the ball(线段树区间更新)
Color the ball 我真的该认真的复习一下以前没懂的知识了,今天看了一下线段树,以前只会用模板,现在看懂了之后,发现还有这么多巧妙的地方,好厉害啊 所以就应该尽量搞懂 弄明白每个知识点 [题 ...
随机推荐
- java算法----排序----(3)冒泡排序
package log; public class Test4 { /** * java算法---冒泡排序 * * @param args */ public static void main(Str ...
- 同一个解决方案或有依赖关系的两个项目引用同名但不同版本的DLL
问题描述 我们最近在使用Redis作Session的集中化,中间碰到了一个如下问题:我们有一些项目比较老,引用了NewtonJson的4.0.3.0版本的DLL,但是Redis提供的C#集成DLL引用 ...
- Codeforces 999D Equalize the Remainders (set使用)
题目连接:Equalize the Remainders 题意:n个数字,对m取余有m种情况,使得每种情况的个数都为n/m个(保证n%m=0),最少需要操作多少次? 每次操作可以把某个数字+1.输出最 ...
- 个人博客地址: furur.xyz
趁着Hexo的热度,最近就买了域名,在GitHub Pages上搭了个人博客.也不是说博客园不好吧,毕竟在博客园三年多,也学到了不少东西,唯一要吐槽的,估计也就是后台管理不方便,markdown无即时 ...
- 用EXCLE群发outlook邮件
Outlookでメール一括送信する方法(差し込み.HTML形式.添付ファイル複数あり) メールを一括送信する方法はウェブ上にいくつも紹介されていましたが.以下のすべての条件を満たすものが見つからなかっ ...
- Linux磁盘空间被占用问题 (分区目录占用空间比实际空间要大: 资源文件删除后, 空间没有真正释放)
问题说明:IDC里的一台服务器的/分区使用率爆满了!已达到100%!经查看发现有个文件过大(80G),于是在跟有关同事确认后rm -f果断删除该文件.但是发现删除该文件后,/分区的磁盘空间压根没有释放 ...
- Gerrit日常维护记录
Gerrit代码审核工具是个好东西,尤其是在和Gitlab和Jenkins对接后,在代码控制方面有着无与伦比的优势. 在公司线上部署了一套Gerrit系统,在日常运维中,使用了很多gerrit命令,在 ...
- v-for v-if || v-else
<el-col> <div v-for="item in resultDetail" class="physical-content" v-i ...
- LINUX内核分析第七周学习总结——可执行程序的装载
LINUX内核分析第六周学习总结——进程的描述和进程的创建 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/cours ...
- selective search
1.引言:图像的物体识别主要有两个步骤:定位.分类.在分类的过程中,需要对图像中文物体的区域划分出来.传统的方法是利用滑窗,一个窗口一个窗口得选择,将之与目标进行比较,确定物体的位置. 为了降低搜索空 ...