题意

给你一个区间,支持如下操作:

  • 在一段区间内加上一个值,并生成一个历史版本
  • 查询某个版本下一段区间内的和
  • 回到一个历史版本上并舍弃之后的版本

做法

这就是主席树区间修改裸题啦QwQ

上一篇博客我讲了主席树可以资瓷单点修改,那么区间修改资不资瓷呢?那当然是资瓷的啦。

就像一般的线段树一样,主席树的一个内部节点也可以存储两个儿子的和,在修改时打标记,在查询时直接返回当前区间的值即可。和单点修改不同的是,区间修改一次最多需要修改线段树上的4个节点(可以脑内证明),也就是说我们需要在历史版本上新建 $ 4log_2n $ 个节点。这个过程在单点修改的基础上稍加修改就可以实现,非常简单。

这时候,你可能会发现一个问题:标记下放时,新版本的标记不就下放到旧版本上去了吗(因为被打标记的区间的两个儿子都指向着历史版本)?

一个解决方法是:每一次下放都新建两个节点以防止标记污染到历史版本。这个可行度很高,然而QwQ...这道题的空间只有狗日的64MB!!!这么做空间吃不消啊(╯‵□')╯︵┻━┻

还有一个更直接的方法是:标记根本就不用下放!由于加法标记是可以累加的,在查询时只要把一路上的标记累加起来,再乘以当前区间长度即可。注意,pushup时不能直接让该节点的值等于子节点的值的和,还要加上当前标记乘以区间长度的值,这样才能让当前节点的标记对它上面的节点产生影响。

事实上,标记永久化也可以用在一般的线段树中。但是一定要注意,标记必须要是可累加的且与顺序无关的。比如又有加法又有乘法就不行。

代码

一定要注意输出格式啊QwQ

//By sclbgw7
#include <cstdio>
#include <cstring>
#include <algorithm>
#define R register
using namespace std;
typedef long long LL;
const int MAXN=100005;
int a[MAXN],n;template<class T>int read(T &x)//这是可以判EOF的快速读入
{x=0;int ff=0;char ch=getchar();while((ch<'0'||ch>'9')&&ch!=EOF){ff|=(ch=='-');ch=getchar();}if(ch==EOF)return 0;while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}x=ff?-x:x;return 1;
}void readc(char &ch)
{ch=getchar();while(ch<'A'||ch>'Z')ch=getchar();
}class CMT
{private:int cnts[MAXN],root[MAXN],cnt,now;struct CMT_node{int l,r,tag;LL x;}node[MAXN*30];void build(int l,int r,int &x){x=++cnt;node[x].tag=0;//一定要清零if(l==r){node[cnt].x=a[l];return;}int m=(l+r)>>1;build(l,m,node[x].l);build(m+1,r,node[x].r);node[x].x=node[node[x].l].x+node[node[x].r].x;}void insert(int st,int en,int l,int r,int &x,int y,int del){x=++cnt,node[x]=node[y];if(st<=l&&en>=r){node[x].tag+=del;node[x].x+=(LL)((r-l+1)*del);return;}int m=(l+r)>>1;if(st<=m)insert(st,en,l,m,node[x].l,node[y].l,del);if(en>m)insert(st,en,m+1,r,node[x].r,node[y].r,del);node[x].x=node[node[x].l].x+node[node[x].r].x+(LL)(r-l+1)*node[x].tag;  //pushup}LL query(int st,int en,int l,int r,int x,int tsum){if(st<=l&&en>=r){LL ans=(LL)((r-l+1)*tsum);ans+=node[x].x;return ans;}int m=(l+r)>>1;LL ans=0;if(st<=m)ans+=query(st,en,l,m,node[x].l,tsum+node[x].tag);if(en>m)ans+=query(st,en,m+1,r,node[x].r,tsum+node[x].tag);return ans;}public:void init(){cnt=now=0;build(1,n,root[0]);cnts[0]=cnt;}void back(int x)//为了节省空间,回退时释放内存{now=x;cnt=cnts[now];}void change(int l,int r,int del){++now;insert(l,r,1,n,root[now],root[now-1],del);cnts[now]=cnt;}LL getsum(int l,int r,int his,int isnow=0){if(isnow)return query(l,r,1,n,root[now],0);return query(l,r,1,n,root[his],0);}
}cmt;int main()
{int m,fl=0;while(read(n)){if(fl)printf("\n");else fl=1;read(m);for(R int i=1;i<=n;++i)read(a[i]);cmt.init();char ch;int t1,t2,t3;for(R int i=1;i<=m;++i){readc(ch);if(ch=='C'){read(t1),read(t2),read(t3);cmt.change(t1,t2,t3);}else if(ch=='Q'){read(t1),read(t2);printf("%lld\n",cmt.getsum(t1,t2,0,1));}else if(ch=='H'){read(t1),read(t2),read(t3);printf("%lld\n",cmt.getsum(t1,t2,t3));}else{read(t1);cmt.back(t1);}}}return 0;
}

转载于:https://www.cnblogs.com/sclbgw7/p/9079418.html

HDU 4348 To the moon(主席树区间修改)相关推荐

  1. HDU - 4348 To the moon(主席树区间更新-标记永久化)

    题目链接:点击查看 题目大意:给出一个初始时长度为 n 的序列,有 m 次操作,每种操作分为下列四种类型: C l r d:新建一个继承了前一个版本的数组,并将区间 [ l , r ] 内的数字都加上 ...

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

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

  3. HDU - 4348To the moon——主席树+区间修改

    HDU - 4348To the moon [题目描述] [题目分析] 题目中说明每次更新后时间都会加1,而且还会需要查询以前的区间,还会需要返回以前的时间,所以是很裸的主席树.区间查询的话我们同样需 ...

  4. HDU 1698 Just a Hook (线段树区间修改+区间查询)

    题目链接: 传送门 题意:Pudge对装备钩子进行若干次的强化,强化分为三种分别对应的价值是1,2,3,在经历过若干次操作后,输出钩子对应的总价值,每次强化都是对钩子进行区间修改 解题思路:在明白了题 ...

  5. hdu 4902 Nice boat(线段树区间修改,输出最终序列)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4902 Problem Description There is an old country and ...

  6. 【模板】线段树区间修改

    区间修改: 区间修改过程类似于区间询问,例如将[ul, ur]内的所有元素都加上v,则进行如下操作: 当当前区间被区间[ul, ur]所包含时, 当前的节点值加上区间长度(r - l  + 1)乘以v ...

  7. python:线段树区间修改 + 区间查询 模板 + 坑点总结

    from functools import reduceclass SegTree:'''支持增量更新,覆盖更新,序列更新,任意RMQ操作基于二叉树实现初始化:O(1)增量更新或覆盖更新的单次操作复杂 ...

  8. HDU - 5919 Sequence II——主席树+区间种类++逆序建树

    [题目描述] HDU - 5919 Sequence II [题目分析] 题目给定一个数组,每次查询一个区间,找出区间内不同数字的个数x,然后输出按出现顺序第x/2向上取整个数字的位置. 按照要求,我 ...

  9. HDU - 6621 K-th Closest Distance——主席树+二分

    [题目描述] HDU - 6621 K-th Closest Distance [题目分析] 因为看到第kkk大的要求,刚开始的时候一直都在想怎么运用第kkk大来解决问题,但是后来看其他人的博客才发现 ...

最新文章

  1. 使用最小堆优化Dijkstra算法
  2. php中查询结果展示
  3. python 播放 wav 文件
  4. 电子火折子的原理,了解一下?
  5. window7 ubuntu12.04 Opensuse13.04 三系统安装
  6. logrotate切割日志rsyslog不重新上传,清空归零iCurrOffs
  7. 不是每个人都适合linux
  8. openpyxl 绘制饼形图_好享学丨快速上手Pythonmatplotlib 箱线图绘制,学术人必备
  9. IDEA : IDEA 打开使用内存监控
  10. Bailian2716 全局变量【字符流】
  11. pythonpandas无列名数据合并_python – Pandas:合并多个数据帧和控制列名?
  12. python 3 导入 迭代判断
  13. RocketMQ(十六)RocketMQ消息存储机制
  14. objective-c 汇编语言,Objective-C和C的区别?
  15. Java开发QQ机器人
  16. 语音助手——未来趋势
  17. 8类网线利弊_网线标准(从一类线到八类线)
  18. 剑指 Offer(C++版本)系列:剑指 Offer 10- I 斐波那契数列
  19. 全球运输工业的升级会带来什么
  20. 计算机显卡型号中数字含义详解,显卡型号中字母和数字所代表的含义.doc

热门文章

  1. matlab地球公转,Unity模拟太阳地球月球公转自转
  2. mysql的mvcc 和next-lock
  3. 分布式系统二、MogileFS
  4. 20155305乔磊2016-2017-2《Java程序设计》第十周学习总结
  5. 通用计算机的雏形是图灵机吗,什么是图灵机和通用计算机
  6. 教你如何解析eth的区块信息,并保存所有的交易记录
  7. 优盘安装OpenThos操作系统OTO
  8. Android ActionBar中Overflow Menu(溢出菜单)中的一些问题
  9. 内核模式 vs 用户模式
  10. 中国软件开发外包公司排名-国内最大的软件开发商有哪些呢