【uoj#164】[清华集训2015]V 线段树维护历史最值
给你一个长度为 $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 线段树维护历史最值的更多相关文章
- UOJ #164 [清华集训2015]V (线段树)
题目链接 http://uoj.ac/problem/164 题解 神仙线段树题. 首先赋值操作可以等价于减掉正无穷再加上\(x\). 假设某个位置从前到后的操作序列是: \(x_1,x_2,..., ...
- LOJ 164 【清华集训2015】V——线段树维护历史最值
题目:http://uoj.ac/problem/164 把操作改成形如 ( a,b ) 表示加上 a 之后对 b 取 max 的意思. 每个点维护当前的 a , b ,还有历史最大的 a , b 即 ...
- 【bzoj3064】Tyvj 1518 CPU监控 线段树维护历史最值
题目描述 给你一个序列,支持4种操作:1.查询区间最大值:2.查询区间历史最大值:3.区间加:4.区间赋值. 输入 第一行一个正整数T,表示Bob需要监视CPU的总时间. 然后第二行给出T个数表示在你 ...
- SPOJ 1557 GSS2 - Can you answer these queries II (线段树+维护历史最值)
都说这题是 GSS 系列中最难的,今天做了一下,名副其实 首先你可以想到各种各样的在线乱搞想法,线段树,主席树,平衡树,等等,但发现都不太可行. 注意到题目也没有说强制在线,因此可以想到离线地去解决这 ...
- 【题解】P4247 [清华集训]序列操作(线段树修改DP)
[题解]P4247 [清华集训]序列操作(线段树修改DP) 一道神仙数据结构(DP)题. 题目大意 给定你一个序列,会区间加和区间变相反数,要你支持查询一段区间内任意选择\(c\)个数乘起来的和.对1 ...
- 滑动窗口(poj,线段树维护区间最值)
题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: The array i ...
- CF213E Two Permutations 线段树维护哈希值
当初竟然看成子串了$qwq$,不过老师的$ppt$也错了$qwq$ 由于子序列一定是的排列,所以考虑插入$1$到$m$到$n-m+1$到$n$; 如何判断呢?可以用哈希$qwq$: 我们用线段树维护哈 ...
- BZOJ 4732 UOJ #268 [清华集训2016]数据交互 (树链剖分、线段树)
题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4732 (UOJ) http://uoj.ac/problem/268 题解 ...
- 清华集训2015 V
#164. [清华集训2015]V http://uoj.ac/problem/164 统计 描述 提交 自定义测试 Picks博士观察完金星凌日后,设计了一个复杂的电阻器.为了简化题目,题目中的常数 ...
随机推荐
- 2016-2017-2 20155322 实验三 敏捷开发与XP实践
2016-2017-2 20155322 实验三 敏捷开发与XP实践 实验内容 XP基础 XP核心实践 相关工具 实验知识点 敏捷开发(Agile Development)是一种以人为核心.迭代.循序 ...
- switchsharp
https://www.switchysharp.com/file/switchysharp-v1.10.4.zip
- 【转载】混编ObjectiveC++
原文:混编ObjectiveC++ 最近有点炒冷饭的嫌疑,不过确实以前没有Git Or Blog的习惯,所以很多工作上的技术分享就存留在了电脑的文档里,现在还是想重新整理一下,再分享出来. 混编C++ ...
- 【转】linux下,如何把整个文件夹上传到服务器(另一台linux)
原文转自:https://zhidao.baidu.com/question/1046040541327493019.html 1.Linux下目录复制:本机->远程服务器 scp -r /h ...
- PHP反序列化漏洞代码审计—学习资料
1.什么是序列化 A.PHP网站的定义: 所有php里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示.unserialize()函数能够重新把字符串变回php原来的值. ...
- Git之hotfix热修复分支
1.假设你正在开发一个新功能, 需要新建一个new分支并切换: git checkout -b new 等价于 git branch new git checkout new 然后在这个new分支上已 ...
- Power Designer逆向工程导入Oracle表,转为模型加注释
1.打开PowerDesigner ——文件——Reverse Engineer——DataBase 2.选择所要连接数据库版本,此处使用的是oracle version 11g. 3.点击红色区域, ...
- 2019展望计划(Lamica 2019-Year Plan):
1,家人身体健康.2,好好上课,考试顺利,不要挂科.3,PETS3 9月份 杭州 一定要过.4,PETS3通过后,进军日语N3-N2.5,在杭州找一份合适的工作(底线6K).6,在杭州交到新朋友.7, ...
- Python基础灬列表&字典生成式
列表生成式 # 求1~10偶数的平方 # 1.常规写法 a_list = [] for i in range(1, 11): if i % 2 == 0: a_list.append(i * i) p ...
- curl常用用法
-v显示请求详细信息 curl www.baidu.com -v -X 指定请求方式 GET请求 curl -X GET http://localhost:8080/search?data=123 # ...