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\),区间赋值,查询单点的值以及单点历史最大值. 解题思路: 观察发现,每一种修改操作都可以用 ...
随机推荐
- HTML网页Table解析
procedure TForm27.Button1Click(Sender: TObject); var doc2: IHTMLDocument2; doc3: IHTMLDocument3; ita ...
- Nexus使用
Nexus使用: Nexus的默认登录账户:admin,密码:admin123. 以下为步骤说明: 1.右上角->login 2.左菜单->security->user->ad ...
- 详述Oracle RAC的五大优势及其劣势
不同的集群产品都有自己的特点,RAC的特点包括如下几点: ·双机并行.RAC是一种并行模式,并不是传统的主备模式.也就是说,RAC集群的所有成员都可以同时接收客户端的请求. ·高可用性.RAC是Ora ...
- SQL语言类别
SQL语言主要分为四大类:数据查询语言DQL,数据操纵语言DML, 数据定义语言DDL,数据控制语言DCL. DQL (data query language) DML(data manipulati ...
- AutoConfig工具使用
下载安装Auto工具包: http://code.taobao.org/mvn/repository/com/alibaba/citrus/tool/antx-autoconfig/1.0.9/ant ...
- python 学习备忘
list列表排序 def listdir(path): #返回一个排序后的目录list files=os.listdir(path) files.sort(key=lambda x:str(x[:-4 ...
- orientdb 学习
简介 OrientDB 是一款 NoSQL 数据库.是一种文档-图数据库.即:既具有文档数据库的特性,又具有图数据库的功能. 端口 2424 OrientDB 监听 二进制 访问的的端口 (即:通过 ...
- java的反射应用
class B{ public static void main(String[] arg){ Class c_a = Class.forName(packageName + "." ...
- 元素的定位id和name
1.元素定位: 元素的定位是自动化测试的核心,要想操作一个元素,首先应该识别这个元素 webdriver提供了一系列的元素定位方法,常用的有以下几种 id name class name partia ...
- ORDER BY 子句在视 图、内联函数、派生表、子查询和公用表表达式中无效
SQL语句: select * from (select distinct t2.issue,cashmoney from (select distinct issue from lot_gamepa ...