题目描述

给你一个长度为 $n$ 的序列,支持五种操作:

$1\ l\ r\ x$ :将 $[l,r]$ 内的数加上 $x$ ;
$2\ l\ r\ x$ :将 $[l,r]$ 内的数减去 $x$ ,并与 $0$ 取 $\text{max}$ ;
$3\ l\ r\ x$ :将 $[l,r]$ 内的数变为 $x$ ;
$4\ y$ :询问第 $y$ 个数的值;
$5\ y$ :询问第 $y$ 个数的历史最大值。

$n,m\le 5\times 10^5,0\le x\le 10^9$


题解

线段树维护历史最值

线段树维护历史最值的方法可以参考 CPU监控 (那道题我是用这道题的方法做的。。。)

那么按照同样的方法,操作1可以看作打标记 $(x,0)$ ,操作2可以看作打标记 $(-x,0)$ ,操作3可以看作打标记 $(-\infty ,x)$ 。

用同样的方法进行标记的维护即可。

由于本题是单点查询,因此可以只考虑标记对原值的影响,不需要维护区间最值及区间历史最值。

时间复杂度 $O(m\log n)$

#include <cstdio>
#include <algorithm>
#define N 500010
#define lson l , mid , x << 1
#define rson mid + 1 , r , x << 1 | 1
using namespace std;
typedef long long ll;
const ll inf = 1ll << 60;
struct data
{
ll x , y;
data(ll a = 0 , ll b = -inf) {x = a , y = b;}
data operator+(const data &a)const {return data(max(x + a.x , -inf) , max(y + a.x , a.y));}
data operator*(const data &a)const {return data(max(x , a.x) , max(y , a.y));}
}ntag[N << 2] , ptag[N << 2];
ll a[N];
inline void pushdown(int x)
{
int l = x << 1 , r = x << 1 | 1;
ptag[l] = ptag[l] * (ntag[l] + ptag[x]);
ntag[l] = ntag[l] + ntag[x];
ptag[r] = ptag[r] * (ntag[r] + ptag[x]);
ntag[r] = ntag[r] + ntag[x];
ptag[x] = ntag[x] = data();
}
void build(int l , int r , int x)
{
ntag[x] = ptag[x] = data();
if(l == r)
{
scanf("%lld" , &a[l]);
return;
}
int mid = (l + r) >> 1;
build(lson) , build(rson);
}
void update(int b , int e , data v , int l , int r , int x)
{
if(b <= l && r <= e)
{
ptag[x] = ptag[x] * (ntag[x] + v);
ntag[x] = ntag[x] + v;
return;
}
pushdown(x);
int mid = (l + r) >> 1;
if(b <= mid) update(b , e , v , lson);
if(e > mid) update(b , e , v , rson);
}
ll query(int p , bool flag , int l , int r , int x)
{
if(l == r)
{
if(flag) return max(a[p] + ptag[x].x , ptag[x].y);
else return max(a[p] + ntag[x].x , ntag[x].y);
}
pushdown(x);
int mid = (l + r) >> 1;
if(p <= mid) return query(p , flag , lson);
else return query(p , flag , rson);
}
int main()
{
int n , m , opt , x , y;
ll z;
scanf("%d%d" , &n , &m);
build(1 , n , 1);
while(m -- )
{
scanf("%d%d" , &opt , &x);
if(opt == 1) scanf("%d%lld" , &y , &z) , update(x , y , data(z , 0) , 1 , n , 1);
if(opt == 2) scanf("%d%lld" , &y , &z) , update(x , y , data(-z , 0) , 1 , n , 1);
if(opt == 3) scanf("%d%lld" , &y , &z) , update(x , y , data(-inf , z) , 1 , n , 1);
if(opt == 4) printf("%lld\n" , query(x , 0 , 1 , n , 1));
if(opt == 5) printf("%lld\n" , query(x , 1 , 1 , n , 1));
}
return 0;
}

【uoj#164】[清华集训2015]V 线段树维护历史最值的更多相关文章

  1. UOJ #164 [清华集训2015]V (线段树)

    题目链接 http://uoj.ac/problem/164 题解 神仙线段树题. 首先赋值操作可以等价于减掉正无穷再加上\(x\). 假设某个位置从前到后的操作序列是: \(x_1,x_2,..., ...

  2. LOJ 164 【清华集训2015】V——线段树维护历史最值

    题目:http://uoj.ac/problem/164 把操作改成形如 ( a,b ) 表示加上 a 之后对 b 取 max 的意思. 每个点维护当前的 a , b ,还有历史最大的 a , b 即 ...

  3. 【bzoj3064】Tyvj 1518 CPU监控 线段树维护历史最值

    题目描述 给你一个序列,支持4种操作:1.查询区间最大值:2.查询区间历史最大值:3.区间加:4.区间赋值. 输入 第一行一个正整数T,表示Bob需要监视CPU的总时间. 然后第二行给出T个数表示在你 ...

  4. SPOJ 1557 GSS2 - Can you answer these queries II (线段树+维护历史最值)

    都说这题是 GSS 系列中最难的,今天做了一下,名副其实 首先你可以想到各种各样的在线乱搞想法,线段树,主席树,平衡树,等等,但发现都不太可行. 注意到题目也没有说强制在线,因此可以想到离线地去解决这 ...

  5. 【题解】P4247 [清华集训]序列操作(线段树修改DP)

    [题解]P4247 [清华集训]序列操作(线段树修改DP) 一道神仙数据结构(DP)题. 题目大意 给定你一个序列,会区间加和区间变相反数,要你支持查询一段区间内任意选择\(c\)个数乘起来的和.对1 ...

  6. 滑动窗口(poj,线段树维护区间最值)

    题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: The array i ...

  7. CF213E Two Permutations 线段树维护哈希值

    当初竟然看成子串了$qwq$,不过老师的$ppt$也错了$qwq$ 由于子序列一定是的排列,所以考虑插入$1$到$m$到$n-m+1$到$n$; 如何判断呢?可以用哈希$qwq$: 我们用线段树维护哈 ...

  8. BZOJ 4732 UOJ #268 [清华集训2016]数据交互 (树链剖分、线段树)

    题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4732 (UOJ) http://uoj.ac/problem/268 题解 ...

  9. 清华集训2015 V

    #164. [清华集训2015]V http://uoj.ac/problem/164 统计 描述 提交 自定义测试 Picks博士观察完金星凌日后,设计了一个复杂的电阻器.为了简化题目,题目中的常数 ...

随机推荐

  1. 20155332 2016-2017-2《Java程序设计》第1周学习总结

    # 20155332 2016-2017-2<Java程序设计>第1周学习总结 教材学习内容总结 课本提问 1.Java平台概论:为什么需要Java程序设计语言? 2.Java平台概论:版 ...

  2. 深入Redis 主从复制原理

    原文:深入Redis 主从复制原理 1.复制过程 2.数据间的同步 3.全量复制 4.部分复制 5.心跳 6.异步复制 1.复制过程 从节点执行 slaveof 命令. 从节点只是保存了 slaveo ...

  3. 浅入tcp

    1.认识TCP tcp协议是传输层协议,它的最主要的3个特点是面向连接.可靠保证.基于字节流.当应用层把数据给tcp层时,注意如果数据大于MSS是要在tcp层进行分段的.tcp协议为了保证不丢包会给每 ...

  4. Zabbix学习之路(五)之MySQL监控

    1.linux-node2节点安装数据库 [root@linux-node2 ~]# yum install -y mariadb-server [root@linux-node2 ~]# syste ...

  5. 无旋treap的区间操作实现

    最近真的不爽...一道维修数列就做了我1上午+下午1h+1晚上+晚上1h+上午2h... 一道不错的自虐题... 由于这一片主要讲思想,代码我放这里了 不会无旋treap的童鞋可以进这里 呵呵... ...

  6. NUnit基本使用方法

    通常的单元测试框架都以他们支持的语言的开头字母加上Unit作为名字,他们统称为xUnit框架.C++的叫做CppUnit,Java的叫做JUnit,.Net的叫做NUnit.当然不是所有的都这么命名, ...

  7. VIN码识别/车架号识别独家支持云识别

    VIN码(车架号)对于懂车的人来说并不陌生,不要小看这一串字符,从VIN码中可以读懂车辆的生产厂家.年代.车型.车身型式及代码.发动机代码及组装地点等信息. 一辆汽车的VIN码也是车辆的唯一身份证明, ...

  8. HTML5 + CSS3 实现地球绕太阳公转

    使用的是正面视角,主要是用 HTML5 + CSS3 来实现,JS只是用来画图. test.html: <!DOCTYPE html> <html> <head> ...

  9. java.lang.Boolean.valueOf(String s)

    简单说,就是s为true(这四个字母大小写任意)时,返回值为true,否则为false public class one { public static void main(String[] args ...

  10. sql server 批量备份数据库

    很多时候,我们都需要将数据库进行备份,当服务器上数据库较多时,不可能一个数据库创建一个定时任务进行备份,这时,就需要进行批量的数据库备份操作,好了,废话不多说,具体实现语句如下: --开启文件夹权限 ...