题目链接

https://www.luogu.org/problemnew/show/P4314

https://www.lydsy.com/JudgeOnline/problem.php?id=3064

分析

其实我是在看吉司机线段树课件时看到这题很感兴趣就跑过来做

显然如果数据小一点可以用分块什么的比较好搞

但是这个数据范围可能用\(log N\)的数据结构更舒服一点

怎么搞呢?请阅读国家集训队2016论文集之《区间最值操作与历史最值问题——杭州学军中学 吉如一》,对,就是我们敬爱可亲的吉司机.

看不懂?实际上就是告诉我们维护6个\(lazy\)_\(tag\):

  1. \(nmx\)表示当前区间最大值,\(add\)表示当前区间加法标记,\(set\)表示当前区间赋值标记

  2. \(pmx\)表示当前区间历史最大值,\(padd\)表示当前区间在下传此标记前时历史最大加法标记,\(pset\)表示当前区间在下传此标记前历史最大赋值标记

这样\(lazy\)_\(tag\)之间的合并就比较显然了

然后再结合论文食用,或是看代码理解一下

当然GXZlegend大佬使用吉司机的另一个方法也是可行的

http://www.cnblogs.com/GXZlegend/p/8315275.html

注意

我查错又查了一个小时

  • 注意不要把\(-inf\)写成\(inf\)

  • 在\(pushdown\)时思维一定要清晰,注意是哪些标记会对其他标记产生影响

代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <iostream>
#define ll long long
#define ri register int
using std::max;
const int inf=0x3f3f3f3f;
const int maxn=100005;
template <class T>inline void read(T &x){
x=0;int ne=0;char c;
while(!isdigit(c=getchar()))ne=c=='-';
x=c-48;
while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
x=ne?-x:x;return ;
}
int n;
int nmx[maxn<<2],add[maxn<<2],set[maxn<<2];
int pmx[maxn<<2],padd[maxn<<2],pset[maxn<<2];
int num[maxn];
int L,R,dta;
void build(int now,int l,int r){
set[now]=nmx[now]=pmx[now]=pset[now]=-inf;
padd[now]=add[now]=0;
if(l==r){
nmx[now]=pmx[now]=num[l];
return ;
}
int mid=(l+r)>>1;
build(now<<1,l,mid);
build(now<<1|1,mid+1,r);
nmx[now]=pmx[now]=max(nmx[now<<1],nmx[now<<1|1]);
return ;
}
inline void pushdown(int now){
if(padd[now]){
pmx[now<<1]=max(pmx[now<<1],nmx[now<<1]+padd[now]);
if(set[now<<1]!=-inf)
pset[now<<1]=max(pset[now<<1],set[now<<1]+padd[now]);
else
padd[now<<1]=max(padd[now<<1],add[now<<1]+padd[now]);
pmx[now<<1|1]=max(pmx[now<<1|1],nmx[now<<1|1]+padd[now]);
if(set[now<<1|1]!=-inf)
pset[now<<1|1]=max(pset[now<<1|1],set[now<<1|1]+padd[now]);
else
padd[now<<1|1]=max(padd[now<<1|1],add[now<<1|1]+padd[now]);
padd[now]=0;
}
if(pset[now]!=-inf){
pmx[now<<1]=max(pmx[now<<1],pset[now]);
pset[now<<1]=max(pset[now<<1],pset[now]);
pmx[now<<1|1]=max(pmx[now<<1|1],pset[now]);
pset[now<<1|1]=max(pset[now<<1|1],pset[now]);
pset[now]=-inf;
}
if(add[now]){
nmx[now<<1]+=add[now];
pmx[now<<1]=max(pmx[now<<1],nmx[now<<1]);
if(set[now<<1]!=-inf){
set[now<<1]+=add[now];
pset[now<<1]=max(pset[now<<1],set[now<<1]);
}
else {
add[now<<1]+=add[now];
padd[now<<1]=max(padd[now<<1],add[now<<1]);
}
nmx[now<<1|1]+=add[now];
pmx[now<<1|1]=max(pmx[now<<1|1],nmx[now<<1|1]);
if(set[now<<1|1]!=-inf){
set[now<<1|1]+=add[now];
pset[now<<1|1]=max(pset[now<<1|1],set[now<<1|1]);
}
else {
add[now<<1|1]+=add[now];
padd[now<<1|1]=max(padd[now<<1|1],add[now<<1|1]);
}
add[now]=0;
}
if(set[now]!=-inf){
nmx[now<<1]=set[now];
pmx[now<<1]=max(pmx[now<<1],nmx[now<<1]);
set[now<<1]=set[now];
pset[now<<1]=max(pset[now<<1],set[now<<1]);
nmx[now<<1|1]=set[now];
pmx[now<<1|1]=max(pmx[now<<1|1],nmx[now<<1|1]);
set[now<<1|1]=set[now];
pset[now<<1|1]=max(pset[now<<1|1],set[now<<1|1]);
set[now]=-inf;
add[now<<1]=add[now<<1|1]=0;
}
return ;
}
void update_add(int now,int l,int r){
if(L<=l&&r<=R){
nmx[now]+=dta;
pmx[now]=max(pmx[now],nmx[now]);
if(set[now]!=-inf){
set[now]+=dta;
pset[now]=max(pset[now],set[now]);
}
else{
add[now]+=dta;
padd[now]=max(padd[now],add[now]);
}
return ;
}
int mid=(l+r)>>1;
pushdown(now);
if(L<=mid)update_add(now<<1,l,mid);
if(mid<R)update_add(now<<1|1,mid+1,r);
nmx[now]=max(nmx[now<<1],nmx[now<<1|1]);
pmx[now]=max(pmx[now<<1],pmx[now<<1|1]);
return ;
}
void update_set(int now,int l,int r){
if(L<=l&&r<=R){
nmx[now]=dta;
pmx[now]=max(pmx[now],dta);
set[now]=dta;
pset[now]=max(pset[now],dta);
add[now]=0;
return ;
}
int mid=(l+r)>>1;
pushdown(now);
if(L<=mid)update_set(now<<1,l,mid);
if(mid<R)update_set(now<<1|1,mid+1,r);
nmx[now]=max(nmx[now<<1],nmx[now<<1|1]);
pmx[now]=max(pmx[now<<1],pmx[now<<1|1]);
return;
}
int query_now(int now,int l,int r){
if(L<=l&&r<=R){
return nmx[now];
}
int ans=-inf,mid=(l+r)>>1;
pushdown(now);
if(L<=mid)ans=max(ans,query_now(now<<1,l,mid));
if(mid<R)ans=max(ans,query_now(now<<1|1,mid+1,r));
nmx[now]=max(nmx[now<<1],nmx[now<<1|1]);
pmx[now]=max(pmx[now<<1],pmx[now<<1|1]);
return ans;
}
int query_history(int now,int l,int r){
if(L<=l&&r<=R){
return pmx[now];
}
int ans=-inf,mid=(l+r)>>1;
pushdown(now);
if(L<=mid)ans=max(ans,query_history(now<<1,l,mid));
if(mid<R)ans=max(ans,query_history(now<<1|1,mid+1,r));
nmx[now]=max(nmx[now<<1],nmx[now<<1|1]);
pmx[now]=max(pmx[now<<1],pmx[now<<1|1]);
return ans;
}
int q;
int main(){
int x,y,z;
char opt[5];
read(n);
for(ri i=1;i<=n;i++)read(num[i]);
build(1,1,n);
read(q);
while(q--){
scanf("%s",opt);
read(x),read(y);
L=x,R=y;
if(opt[0]=='Q'){
printf("%d\n",query_now(1,1,n));
}
else if(opt[0]=='A'){
printf("%d\n",query_history(1,1,n));
}
else if(opt[0]=='P'){
read(dta);
update_add(1,1,n);
}
else{
read(dta);
update_set(1,1,n);
}
}
return 0;
}

目前洛谷rank 2,在BZOJ上被吊打

洛谷题解P4314CPU监控--线段树的更多相关文章

  1. 题解——洛谷P2781 传教(线段树)

    可以说是数据结构学傻了的典型案例了 昨天跳到这题上 然后思考了一下 噫!好!线段树裸题 然后打完板子,发现\(  n \le 10^9 \) 显然线段树直接做不太行 然后这题又只有普及的难度 然后我就 ...

  2. 【BZOJ】1012: [JSOI2008]最大数maxnumber /【洛谷】1198(线段树)

    Description 现在请求你维护一个数列,要求提供以下两种操作:1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度.2. 插 ...

  3. 洛谷P3372/poj3468(线段树lazy_tag)(询问区间和,支持区间修改)

    洛谷P3372 //线段树 询问区间和,支持区间修改 #include <cstdio> using namespace std; struct treetype { int l,r; l ...

  4. 洛谷P4428二进制 [BJOI2018] 线段树

    正解:线段树 解题报告: 传送门! 话说开始看到这题的时候我想得hin简单 因为关于%3有个性质就是说一个数的各个位数之和%3=这个数%3嘛,小学基础知识? 我就想着,就直接建一棵树,只是这棵树要用个 ...

  5. BZOJ2141&洛谷1975 排队 【线段树套treap】

    题目 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和. 红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的身高有所区别,排 ...

  6. 洛谷P3707 [SDOI2017]相关分析(线段树)

    题目描述 Frank对天文学非常感兴趣,他经常用望远镜看星星,同时记录下它们的信息,比如亮度.颜色等等,进而估算出星星的距离,半径等等. Frank不仅喜欢观测,还喜欢分析观测到的数据.他经常分析两个 ...

  7. 【洛谷P2894】Hotel 线段树+二分查询

    题目大意:给定一个长度为 N 的序列,每个点有两种状态 1/0,表示占有和空闲,现支持 first-fit 查询是否有一段连续的长度为 X 的空闲子序列和区间赋值操作. 题解:get到了线段树新技能. ...

  8. 洛谷$P2486\ [SDOI2011]$染色 线段树+树链剖分

    正解:线段树+树链剖分 解题报告: 传送门$QwQ$ 其实是道蛮板子的题,,,但因为我写得很呆然后写了贼久之后发现想法有问题要重构,就很难受,就先写个题解算了$kk$ 考虑先跑个树剖,然后按$dfn$ ...

  9. 洛谷$P1712\ [NOI2016]$区间 线段树

    正解:线段树 解题报告: 传送门$QwQ$ $umm$很久以前做的了来补个题解$QwQ$ 考虑给每个区间按权值($r-l$从大往小排序,依次加入,然后考虑如果有一个位置被覆盖次数等于$m$了就可以把权 ...

随机推荐

  1. Vue之混入(mixin)与全局混入

    Vue之混入(mixin)与全局混入 接下来通过一个简单的例子看看混入的基础用法: 首先新建一个mixin.js文件,添加以下代码. let mixin = { data() { return { m ...

  2. react中回车enter事件处理

    对于常见的搜索需求业务场景,用户输入完成后,点击enter事件请求数据,要求不提交页面,实现数据局部更新,这需要用到react中的表单Forms. 处理方法: (1)html书写 form标签中去掉a ...

  3. ceph对接openstack环境(4)

    ceph对接openstack环境 环境准备: 保证openstack节点的hosts文件里有ceph集群的各个主机名,也要保证ceph集群节点有openstack节点的各个主机名 一.使用rbd方式 ...

  4. IDEA 2017 安装和破解

    IDEA 2017 下载地址 链接:http://pan.baidu.com/s/1qXNa9UO 密码:9wwg 激活注册码:http://xidea.online 1-选择安装地址 2-选择安装的 ...

  5. 开题报告中如何将一段文字插入到word表格中

    1,举例如下,打开空白word,设计一个20列的表格.任意一段文字. 2,选中这段文字,点击替换按钮.查找内容为“?”,替换为“^&,”(后面是逗号),并勾选“使用通配符”. 3,全部替换得到 ...

  6. java数据结构之HashSet和TreeSet以及LinkedHashSet

    一.HashSet源码注释 public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cl ...

  7. VMware中为CentOS配置静态ip并可访问网络-windows下的VMware

    首先确保虚拟网卡(VMware Network Adapter VMnet8)是开启的,然后在windows的命令行里输入“ipconfig /all”,找到VMware Network Adapte ...

  8. PHP非对称加密

    加密的类型: 在日常设计及开发中,为确保数据传输和数据存储的安全,可通过特定的算法,将数据明文加密成复杂的密文.目前主流加密手段大致可分为单向加密和双向加密. 单向加密:通过对数据进行摘要计算生成密文 ...

  9. [机器学习理论] 降维算法PCA、SVD(部分内容,有待更新)

    几个概念 正交矩阵 在矩阵论中,正交矩阵(orthogonal matrix)是一个方块矩阵,其元素为实数,而且行向量与列向量皆为正交的单位向量,使得该矩阵的转置矩阵为其逆矩阵:  其中,为单位矩阵. ...

  10. vue-wechat-title动态修改title

    在使用Vue制作项目的过程中,发现title没有变化 所以使用vue-wechat-title插件动态修改tilte 一.安装 npm vue-wechat-title --save 二.引入和使用 ...