2018.07.28 uoj#164. 【清华集训2015】V(线段树)
传送门
线段树好题。
要求支持的操作:
1.区间变成max(xi−a,0)" role="presentation" style="position: relative;">max(xi−a,0)max(xi−a,0)
2.区间加
3.区间覆盖
4.询问单点最值
5.询问单点历史最值
注:以下提到的标记都是向下传递的懒标记。
这题直接更新区间最大值貌似不好维护,因此我们需要更换思路,对于每个节点维护一个标记(a,b)" role="presentation" style="position: relative;">(a,b)(a,b),来表示在上一次修改这个区间之后当前区间的所有数都变成(xi+a,b)" role="presentation" style="position: relative;">(xi+a,b)(xi+a,b),这样的话,第一个操作变成了(−a,0)" role="presentation" style="position: relative;">(−a,0)(−a,0),第二个操作变成了(a,−inf)" role="presentation" style="position: relative;">(a,−inf)(a,−inf),第三个操作变成了(−inf,a)" role="presentation" style="position: relative;">(−inf,a)(−inf,a)。然后查询的时候只用查询单点的(a,b)" role="presentation" style="position: relative;">(a,b)(a,b),然后输出(xi+a,b)" role="presentation" style="position: relative;">(xi+a,b)(xi+a,b)的较大值就行了。
然后我们考虑这个标记如何合并,假设现在已经有了一个标记(a,b)" role="presentation" style="position: relative;">(a,b)(a,b),从父亲节点传过来了一个标记(c,d)" role="presentation" style="position: relative;">(c,d)(c,d),那么原本这个点的最大值是max(xi+a,b)" role="presentation" style="position: relative;">max(xi+a,b)max(xi+a,b),现在就变成了max(max(xi+a,b)+c,d)" role="presentation" style="position: relative;">max(max(xi+a,b)+c,d)max(max(xi+a,b)+c,d),也就是max(xi+a+b,b+c,d)" role="presentation" style="position: relative;">max(xi+a+b,b+c,d)max(xi+a+b,b+c,d),也就是max(xi+a+b,max(b+c,d))" role="presentation" style="position: relative;">max(xi+a+b,max(b+c,d))max(xi+a+b,max(b+c,d)),所以这个节点的标记就被更新成了(a+b,max(b+c,d))" role="presentation" style="position: relative;">(a+b,max(b+c,d))(a+b,max(b+c,d))。所以这个标记是可合并的。
然而,我们仍然不能够维护历史单点最大值,因此我们还需要维护一个(hisa,hisb)" role="presentation" style="position: relative;">(hisa,hisb)(hisa,hisb)标记,表示在上一次修改这个区间之后xi" role="presentation" style="position: relative;">xixi最大的历史增量和最大的历史取max" role="presentation" style="position: relative;">maxmax标记,最后同样是查询单点的(hisa,hisb)" role="presentation" style="position: relative;">(hisa,hisb)(hisa,hisb),然后输出(xi+hisa,hisb)" role="presentation" style="position: relative;">(xi+hisa,hisb)(xi+hisa,hisb)的较大值。
这时我们应该大胆的猜想一个节点的history" role="presentation" style="position: relative;">historyhistory标记也是可以合并的。仔细想想,如果从父亲节点传来了一个(a,b,hisa,hisb)" role="presentation" style="position: relative;">(a,b,hisa,hisb)(a,b,hisa,hisb),那么显然是用父亲的hisa" role="presentation" style="position: relative;">hisahisa和自己的a" role="presentation" style="position: relative;">aa来更新自己的hisa" role="presentation" style="position: relative;">hisahisa,然后用父亲的hisa" role="presentation" style="position: relative;">hisahisa和自己的b" role="presentation" style="position: relative;">bb,以及父亲的hisb" role="presentation" style="position: relative;">hisbhisb来更新自己的hisb" role="presentation" style="position: relative;">hisbhisb。
也就是hisa=max(hisa,fa.hisa+a),hisb=max(hisb,max(fa.hisb,fa.hisa+b))" role="presentation" style="position: relative;">hisa=max(hisa,fa.hisa+a),hisb=max(hisb,max(fa.hisb,fa.hisa+b))hisa=max(hisa,fa.hisa+a),hisb=max(hisb,max(fa.hisb,fa.hisa+b))
代码:
#include<bits/stdc++.h>
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
#define inf 1000000000000000000
#define N 500005
#define ll long long
using namespace std;
int n,m,op,l,r;
ll a[N],v;
struct Node{int l,r;ll a,b,his_a,his_b;}T[N<<2];
inline ll max(ll a,ll b){return a>b?a:b;}
inline void operator+=(Node&x,Node y){
x.his_a=max(x.his_a,y.his_a+x.a);
x.his_b=max(x.his_b,max(x.b+y.his_a,y.his_b));
x.a=max(x.a+y.a,-inf);
x.b=max(x.b+y.a,y.b);
}
inline void cle(int p){T[p].his_a=T[p].a=0,T[p].his_b=T[p].b=-inf;}
inline void pushdown(int p){T[lc]+=T[p],T[rc]+=T[p],cle(p);}
inline void build(int p,int l,int r){
T[p].l=l,T[p].r=r,cle(p);
if(l==r)return;
build(lc,l,mid),build(rc,mid+1,r);
}
inline void update(int p,int ql,int qr,Node v){
if(ql>T[p].r||qr<T[p].l)return;
if(ql<=T[p].l&&T[p].r<=qr){T[p]+=v;return;}
if(T[p].l!=T[p].r)pushdown(p);
if(qr<=mid)update(lc,ql,qr,v);
else if(ql>mid)update(rc,ql,qr,v);
else update(lc,ql,mid,v),update(rc,mid+1,qr,v);
}
inline Node query(int p,int k){
if(T[p].l==T[p].r)return T[p];
pushdown(p);
if(k<=mid)return query(lc,k);
return query(rc,k);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)scanf("%lld",&a[i]);
build(1,1,n);
while(m--){
scanf("%d",&op);
if(op==1)scanf("%d%d%lld",&l,&r,&v),update(1,l,r,(Node){l,r,v,-inf,v,-inf});
if(op==2)scanf("%d%d%lld",&l,&r,&v),update(1,l,r,(Node){l,r,-v,0,-v,0});
if(op==3)scanf("%d%d%lld",&l,&r,&v),update(1,l,r,(Node){l,r,-inf,v,-inf,v});
if(op==4){scanf("%d",&l);Node t=query(1,l);printf("%lld\n",max(a[l]+t.a,t.b));}
if(op==5){scanf("%d",&l);Node t=query(1,l);printf("%lld\n",max(a[l]+t.his_a,t.his_b));}
}
return 0;
}
2018.07.28 uoj#164. 【清华集训2015】V(线段树)的更多相关文章
- UOJ #164 [清华集训2015]V (线段树)
题目链接 http://uoj.ac/problem/164 题解 神仙线段树题. 首先赋值操作可以等价于减掉正无穷再加上\(x\). 假设某个位置从前到后的操作序列是: \(x_1,x_2,..., ...
- 【uoj#164】[清华集训2015]V 线段树维护历史最值
题目描述 给你一个长度为 $n$ 的序列,支持五种操作: $1\ l\ r\ x$ :将 $[l,r]$ 内的数加上 $x$ :$2\ l\ r\ x$ :将 $[l,r]$ 内的数减去 $x$ ,并 ...
- 【题解】P4247 [清华集训]序列操作(线段树修改DP)
[题解]P4247 [清华集训]序列操作(线段树修改DP) 一道神仙数据结构(DP)题. 题目大意 给定你一个序列,会区间加和区间变相反数,要你支持查询一段区间内任意选择\(c\)个数乘起来的和.对1 ...
- 清华集训2015 V
#164. [清华集训2015]V http://uoj.ac/problem/164 统计 描述 提交 自定义测试 Picks博士观察完金星凌日后,设计了一个复杂的电阻器.为了简化题目,题目中的常数 ...
- BZOJ 4732 UOJ #268 [清华集训2016]数据交互 (树链剖分、线段树)
题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4732 (UOJ) http://uoj.ac/problem/268 题解 ...
- 2018.07.28 uoj#169. 【UR #11】元旦老人与数列(线段树)
传送门 线段树好题. 维护区间加,区间取最大值,维护区间最小值,历史区间最小值. 同样先考虑不用维护历史区间最小值的情况,这个可以参考这道题的解法,维护区间最小和次小值可以解决前两个操作,然后使用历史 ...
- 2018.07.27 bzoj3064: Tyvj 1518 CPU监控(线段树)
传送门 线段树好题. 维护区间加,区间覆盖,区间最大,区间历史最大. 这个东西在国家集训队2016论文集之<区间最值操作与历史最值问题--杭州学军中学 吉如一>中讲的已经很详细了. 简单来 ...
- 2018.07.27 bzoj4695: 最假女选手(线段树)
传送门 线段树好题 支持区间加,区间取min" role="presentation" style="position: relative;"> ...
- 「清华集训2015」V
「清华集训2015」V 题目大意: 你有一个序列,你需要支持区间加一个数并对 \(0\) 取 \(\max\),区间赋值,查询单点的值以及单点历史最大值. 解题思路: 观察发现,每一种修改操作都可以用 ...
随机推荐
- angular 使用服务共享数据需要注意
在使用服务共享数据时,需要注意一些细节,否则会出现视图不刷新,也不报错这样的问题,遇到了,总结下 如下: <div ng-controller='ctr1'> <a href={{n ...
- XE4 TStringDynArray 比 c6 的TStringList 好用 字符串 分解 分割 转换 TByteDynArray
TStringDynArray 动态数组 字符串 分解 分割 System::DynamicArray<System::UnicodeString> TByteDynArray, ...
- MyEclipse jsp 中文乱码
在最开始加上 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8 ...
- import 语句用于导入从外部模块,另一个脚本等导出的函数,对象或原语。
import 语句用于导入从外部模块,另一个脚本等导出的函数,对象或原语. 注意:此功能目前无法在任何浏览器中实现.它在许多转换器中实现,例如 Traceur Compiler , Babel , R ...
- nginx访问静态文件配置
通过nginx访问静态文件配置,均是在server模块中配置,有两种方式: 1.alias 通过alias关键字,重定义路径,如 server{ listen 7001; server ...
- 迷你MVVM框架 avalonjs 学习教程20、路由系统
SPA的成功离开不这三个东西,分层架构,路由系统,储存系统.分层架构是我们组织复杂代码的关键,这里特指MVVM的avalon:路由系统是将多个页面压缩在一个页面的关键:储存系统特指本地储存,是安全保存 ...
- swagger ui
You can pull a pre-built docker image of the swagger-ui directly from Dockerhub: docker pull swagger ...
- docker registry2
https://blog.csdn.net/mideagroup/article/details/52052618
- win10磁盘碎片整理
如果我们想要加快win10系统运行速度的话,就需要定期整理碎片才可以,减少卡顿,提高性能. 一:注意事项 固态硬盘用户千万不要使用‘磁盘碎片整理功能’,因为使用的技术不一样,使用window自带的该功 ...
- https 证书传递、验证和数据加密、解密过程解析
我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取.所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议. HTTPS简介 HTTPS其实是有两部分组成:HTTP + SSL ...