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\),区间赋值,查询单点的值以及单点历史最大值. 解题思路: 观察发现,每一种修改操作都可以用 ...
随机推荐
- SQL 2008 启用和禁用xp_cmdshell
xp_,cmd,cmdshell -- 允许配置高级选项EXEC sp_configure 'show advanced options', 1GO-- 重新配置RECONFIGUREGO-- 禁用x ...
- 内容方框 fieldset
Title 登录 用户名 密码 <!DOCTYPE html><html lang="en"><head> <meta charset=& ...
- pandas datafram重命名列名称
方法一: 直接给column赋值 df.columns=["a", "b"], 所有的column全部重命名 example: import pandas as ...
- NTP时间服务器搭建
系统时区设置::: 查看当前时区# date -R修改系统时区# timeconfig 或# cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtim ...
- jps command not found已解决
根据当前版本安装devel 包 eg: yum install java--openjdk-devel -y jdk小工具jps介绍 jps(Java Virtual Machine Process ...
- java.lang.IllegalArgumentException: Service not registered
java.lang.IllegalArgumentException: Service not registered 首先检查一下,Service是否在AndroidManifest文件中注册.格式如 ...
- Hibernate查询方式(补)
-----------------siwuxie095 Hibernate 查询方式 1.对象导航查询 根据已经加载的对 ...
- PHP的zip、unzip类详解
1.打开一个ZIP包,用于读取.写入或修改 open(string $filename [, int $flags]) $filename - 文件名 $flags - 打开模式 ZIPARCHIVE ...
- 在Objc项目中调用Swift
之前的文字中记录了在Swift项目中调用OC的相关代码,比较简单直接 传送门 但是在OC中调用swift代码则不是那么的和谐,网络上很多文章业已经有点陈旧.记录步骤如下: 1.创建OC项目 (1)启动 ...
- 平衡二叉树Balanced Binary Tree
[抄题]: Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced b ...