链接: 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 (主席树 区间更新)的更多相关文章

  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(主席树 区间更新)题解

    题意: 给一个数组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步操作 思路: ...

  9. 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 ...

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

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

随机推荐

  1. 前后端交互json字符串

    //将需要的参数转成json字符串,然后用utf-8编码 var obj = encodeURIComponent(JSON.stringify(this.categories),"utf- ...

  2. Django学习篇(第二部)

    4.Django pip3 install django C:\Python35\Scripts # 创建Django工程 django-admin startproject [工程名称] mysit ...

  3. linux编程头文件所在路径的问题

    一.问题引入 1.头文件与库 当我们在PC主机linux环境下(如ubuntu),编写linux应用程序,然后利用gcc来编译.在源代码的开始位置会写入头文件,那是因为我们使用了系统提供的库函数,例如 ...

  4. python3 installed 安装 pip3

    curl -sS https://bootstrap.pypa.io/get-pip.py | sudo python3

  5. 一头雾水的"Follow The Pointer"

    原文:一头雾水的"Follow The Pointer" 一头雾水的"Follow The Pointer"                           ...

  6. KMeans算法分析以及实现

    KMeans KMeans是一种无监督学习聚类方法, 目的是发现数据中数据对象之间的关系,将数据进行分组,组内的相似性越大,组间的差别越大,则聚类效果越好. 无监督学习,也就是没有对应的标签,只有数据 ...

  7. ubuntu12.04安装mininet

    网上安装mininet教程有很多,都是通过git命令安装,但有一个坑,安装到./install.sh时会报错,记录下来 1.通过git 下载mininet git clone git://github ...

  8. BodeAbp概述

    BodeAbp框架基于github开源框架ASP.NET Boilerplate,abp项目地址:https://github.com/aspnetboilerplate/aspnetboilerpl ...

  9. 【精】【入门篇】js正则表达式

    前言 最近有了点时间,就回头看了一下<学习正则表达式>这本书.怎么说呢,这本书适合从零开始学习正则表达式或者有一点基础但是想要加强这方面能力的读者.这本书的风格是“实践出真知”,使用归纳方 ...

  10. width,height为多少px时,A4纸打印时刚好一页?

    计算方式一般的分辨率为XX像素/英寸,其中一英寸为25.4毫米.所以一毫米的像素数就为XX/25.4.现在的工作就是求XX的值了,把XX的值求出来以后,直接用XX/25.4 * 210就得到A4纸的像 ...