CPU监控 线段树裸题
LINK:bzoj3064 此题甚好码了20min停下来思考的时候才发现不对的地方有点坑...
还真不好写来着 可这的确是线段树的裸题...我觉得我写应该没有什么大问题 不过思路非常的紊乱 如果是自己写的话 所以为了自己能写出来 整理思路就是这篇博客了。
Q X Y:询问从X到Y这段时间内CPU最高使用率
A X Y:询问从X到Y这段时间内之前列出的事件使CPU达到过的最高使用率
P X Y Z:列出一个事件这个事件使得从X到Y这段时间内CPU使用率增加Z
C X Y Z:列出一个事件这个事件使得从X到Y这段时间内CPU使用率变为Z
4个询问 观察如果没有第二个询问的话那么这将是一个线段树维护两个标记且维护区间最大值的操作 很好写。
能否标记永久化?学了就应该思考一下能否标记永久化 好像有点繁杂两个标记互相干扰 不过应该没有什么大问题 但是加上区间最值就不太好写了 所以对于多个标记且互相影响且维护历史最值应该是做不了的 建议pushdown更好一点。
综上 线段树 的lazy tag 和标记永久化都是选自哪一种好写写哪一个,这里推荐写lazy tag代码复杂度不算太高。
考虑如何维护历史最值 这个z可能是负数 如果简单的开一个标记mx表示历史最值的话对于一次区间 的修改 考虑一件事情pushdown未传递之时一个区间覆盖的标记打过来直接add标记被覆盖掉么 那么历史最值可就会出错 其子树内部的最值标记是应该被更新掉的。
现在没有被更新 所以这一点上来看是不太正确的 当然也有另一种情况 区间覆盖标记覆盖原本的标记 这样的话历史最值也会出现一些大问题。如何解决 针对上述情况我想了一个再覆盖标记的时候 先把被覆盖的标记进行下传然后再覆盖标记 让下传的标记先虽然对目前的值是没有什么大影响的但是对历史最值是有可能更新的所以需要这样做 再down中我突然意识到了一个比较严肃的问题关于add标记的合并问题 我们显然每次不能down到儿子那样复杂的会异常的大每次操作接近4n的复杂度比普通的数组模拟复杂度更高。
add标记合并也会带来影响 原本的add比较大现在合并了变小了 可是上一次的add显然更可能更新历史最值这样历史最值还是一个错误的东西。还要考虑怎么再down的时候维护这个标记。我们设定一个下传时候的addmax 再来一个tagmax 钦定下传然后再标准下传我觉得这样很稳复杂度的话 nlogn 好像是多了近乎2/3的常数。
大概是这样的一个毒瘤的东西吧 写完才知道正确与否理性的看是正确的。答案再32位有符号整数内 int 2^31-1好像只有31位靠 非得开long long 增加一倍的大常数 看看能过不能吧...
有点崩溃 代码难度有点高 不知道怎么写 按照上面的思路还有一些细节要处理 啊 我是真的难受 服了这毒瘤线段树 好好的维护什么区间历史最值 真是服了...
又杠了30min 还是感觉 这不是人写的东西 pushdown 和down down里面我觉得还需要下传东西 这样的话下传覆盖儿子也得下传覆盖 故我这思路不太可取还是看看dalao怎么写的吧 我崩溃了200+的代码 总有点纰漏之处。
应该是我对这个标记有点什么误解 被我搞麻烦了 正确的题解是吉如一老师提出的标记合并法解决的。内心无比崩溃。
粘一下 吉老师的题解:
刚接触这一类问题时,这个例题的难度可能较高,所以我们先忽略区间赋值操作。
考虑使用传统的懒标记来解决,首先如果只是询问区间最大值,只面要使用区间加减这一个懒标记(用 Add 表示)就能解决。
现在考虑询问区间历史最大值的最大值。我们定义一种新的懒标记:历史最大的加减标记(用 Pre 表示)。这个标记的定义是:从上一次把这个节点的标记下传的时刻到当前时刻这一时间段中,这个节点中的 Add 标记值到达过的最大值。
现在考虑把第 i 个节点的标记下传到它的儿子 l ,不难发现标记是可以合并的:Prel=max(Prel,Addl+Prei),Addl=Addl+Addi;Prel=max(Prel,Addl+Prei),Addl=Addl+Addi 。至于区间历史最大值信息的更新也与标记的合并类似,只面要将当前的区间最大值加上 Prei 然后与原来的历史最大值进行比较即可。
现在回到原题,我们观察在修改操作过程中,被影响到的节点的变化:如果一个节点没有发生标记下传,那么最开始它一直被区间加减操作所影响,这时我们可以用上面描述的Pre标记来记录,直到某一时刻,这个节点被区间覆盖标记影响A,那么这时这个节点中的所有数都变得完全相同,再之后的所有区间加减修改,对这个节点来说,与区间覆盖操作并没有不同。
因此每一个节点受到的标记可以分成两个部分:第一个部分是区间加减,第二个部分是区间覆盖。因此我们可以用 (x,y) 来表示历史最值标记,它的定义是当前区间在第一阶段时最大的加减标记是 xx ,在第二个阶段时最大的覆盖标记是 yy 。显然这个标记是可以进行合并与更新的。
到此我们就使用最传统的懒标记方法解决了这个问题,时间复杂度 O(mlogn) 。
其实我没怎么看懂 但是这题是 神题经过我的不断思索 决定抄一遍...(学会了一个标记法...
//#include<bits/stdc++.h>
#include<iostream>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<cctype>
#include<utility>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<deque>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<iomanip>
#include<stack>
#include<string>
#include<cstring>
#define INF 1000000000000ll
#define ll long long
#define db double
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
#define l(p) t[p].l
#define r(p) t[p].r
#define sum(p) t[p].sum
#define mx(p) t[p].mx
#define zz p<<1
#define yy p<<1|1
using namespace std;
char buf[<<],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
}
inline ll read()
{
ll x=,f=;char ch=getc();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
return x*f;
}
const ll MAXN=;
ll n,m;
char ch;
struct wy
{
ll l,r;
ll mx;//历史最值
ll sum;//当前最值
}t[MAXN<<];
struct data
{
ll x,y;
data(ll a=,ll b=-INF){x=a;y=b;}
data operator +(const data &a){return data(max(-INF,x+a.x),max(y+a.x,a.y));}
data operator *(const data &a){return data(max(x,a.x),max(y,a.y));}
}ntag[MAXN<<],ptag[MAXN<<];
inline void pushup(ll p)
{
mx(p)=max(mx(zz),mx(yy));
sum(p)=max(sum(zz),sum(yy));
}
inline void pushdown(ll p)
{
ptag[zz]=ptag[zz]*(ntag[zz]+ptag[p]);
ntag[zz]=ntag[zz]+ntag[p];
mx(zz)=max(mx(zz),max(sum(zz)+ptag[p].x,ptag[p].y));
sum(zz)=max(sum(zz)+ntag[p].x,ntag[p].y);
ptag[yy]=ptag[yy]*(ntag[yy]+ptag[p]);
ntag[yy]=ntag[yy]+ntag[p];
mx(yy)=max(mx(yy),max(sum(yy)+ptag[p].x,ptag[p].y));
sum(yy)=max(sum(yy)+ntag[p].x,ntag[p].y);
ptag[p]=ntag[p]=data();
}
inline void build(ll p,ll l,ll r)
{
l(p)=l;r(p)=r;
if(l==r)
{
mx(p)=read();sum(p)=mx(p);
return;
}
ll mid=(l+r)>>;
build(zz,l,mid);
build(yy,mid+,r);
pushup(p);
}
inline void change(ll p,ll l,ll r,data a)
{
if(l<=l(p)&&r>=r(p))
{
ntag[p]=ntag[p]+a;
ptag[p]=ptag[p]*ntag[p];
sum(p)=max(sum(p)+a.x,a.y);
mx(p)=max(mx(p),sum(p));
return;
}
ll mid=(l(p)+r(p))>>;
pushdown(p);
if(l<=mid)change(zz,l,r,a);
if(r>mid)change(yy,l,r,a);
pushup(p);
}
inline ll ask(ll p,ll l,ll r,ll flag)
{
if(l<=l(p)&&r>=r(p))return flag?mx(p):sum(p);
pushdown(p);
ll mid=(l(p)+r(p))>>,ans=-INF,w=-INF;
if(l<=mid)ans=ask(zz,l,r,flag);
if(r>mid)w=ask(yy,l,r,flag);
return max(ans,w);
}
signed main()
{
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
n=read();
build(,,n);
m=read();
for(ll i=;i<=m;++i)
{
ll x,y,z;
ch=getc();
while(ch!='Q'&&ch!='A'&&ch!='P'&&ch!='C')ch=getc();
x=read();y=read();
if(ch=='Q')printf("%lld\n",ask(,x,y,));
if(ch=='A')printf("%lld\n",ask(,x,y,));
if(ch=='P')z=read(),change(,x,y,data(z,-INF));
if(ch=='C')z=read(),change(,x,y,data(-INF,z));
}
return ;
}
CPU监控 线段树裸题的更多相关文章
- POJ 3468 线段树裸题
这些天一直在看线段树,因为临近期末,所以看得断断续续,弄得有些知识点没能理解得很透切,但我也知道不能钻牛角尖,所以配合着刷题来加深理解. 然后,这是线段树裸题,而且是最简单的区间增加与查询,我参考了A ...
- 【bzoj3064】Tyvj 1518 CPU监控 线段树维护历史最值
题目描述 给你一个序列,支持4种操作:1.查询区间最大值:2.查询区间历史最大值:3.区间加:4.区间赋值. 输入 第一行一个正整数T,表示Bob需要监视CPU的总时间. 然后第二行给出T个数表示在你 ...
- BZOJ1067&P2471 [SCOI2007]降雨量[线段树裸题+细节注意]
dlntqlwsl 很裸的一道线段树题,被硬生生刷成了紫题..可能因为细节问题吧,我也栽了一次WA50分.不过这个隐藏条件真的对本菜鸡来说不易发现啊. 未知的年份连续的就看成一个就好了,把年份都离散化 ...
- 【LOJ6029】「雅礼集训 2017 Day1」市场(线段树裸题)
点此看题面 大致题意: 维护序列,支持区间加法,区间除法(向下取整),区间求\(min\)和区间求和. 线段树维护区间除法 区间加法.区间求\(min\)和区间求和都是线段树基本操作,因此略过不提. ...
- BZOJ.3064.CPU监控(线段树 历史最值)
题目链接 \(Description\) 有一个长为n的序列Ai,要求支持查询[l,r]的最值.历史最值,区间加/重设 \(Solution\) 线段树,每个点再维护一个历史(从0到现在)最大值.历史 ...
- HDU1166 线段树裸题 区间求和
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- HDU 4893 线段树裸题
Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Oth ...
- cdoj 1324 卿学姐与公主 线段树裸题
卿学姐与公主 Time Limit: 2000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit St ...
- BZOJ3064 Tyvj 1518 CPU监控 线段树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3064 题意概括 一个序列,要你支持以下操作: 1. 区间询问最大值 2. 区间询问历史最大值 3. ...
随机推荐
- OldTrafford after 102 days
THE RED GO MARCHING ON One Team One Love Through the highs and the lows One hundred and two long ...
- ansible 2.7 API
# coding:utf-8 # @Time : 2019-01-14 15:22 # @Author : 小贰 # @FileName: ansible_sync_hosts.py # @funct ...
- POJ2376贪心
题意:数轴上有 n (1<=n<=25000)个闭区间 [ai, bi],选择尽量少的区间覆盖一条指定线段 [1,t](1<=t<=1,000,000).覆盖整点,即[1,2] ...
- 二分查找&二叉排序树
首先我们先来复习一下二分查找的算法 对于正向序列的二分查找 递归实现: bool binary_search(vector<int> &sort_arry,int begin,in ...
- BFC原理解析
BFC的概念 块格式化上下文(Block Formatting Context,BFC) 是Web页面的可视化CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域. 它是 ...
- 数据可视化之DAX篇(三) 认识DAX中的表函数和值函数
https://zhuanlan.zhihu.com/p/64421003 学习 DAX 的过程中,会遇到各种坑,刚开始甚至无法写出一个正确的度量值,总是提示错误.其实很多原因都是不理解 DAX 函数 ...
- Spring Boot 2.3.0正式发布:优雅停机、配置文件位置通配符新特性一览
当大潮退去,才知道谁在裸泳..关注公众号[BAT的乌托邦]开启专栏式学习,拒绝浅尝辄止.本文 https://www.yourbatman.cn 已收录,里面一并有Spring技术栈.MyBatis. ...
- 计算机网络期末实验考题(Pacekt Tracer搭建网络拓扑实现通信)
期末考试的这一道实验题目具体要求如下: 搭建一个包含5个路由器.两个交换机和3个PC机的连通网络,网络拓扑结构自定,网络IP地址,子网掩码等信息自定, 最后实现3个PC机互通.要求:1)3个PC ...
- 【一起学系列】之命令模式:封装一个简单Jedis
意图 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤销的操作. 命令模式的诞生 [产品]:开发小哥,来活啦,咱们需要设计一款遥控器,核心功能就 ...
- 使用nvm安装node,运行node报错 node: command not found
1. 使用nvm安装node之后,直接运行node命令会报错 node: command not found 需要使用nvm ls 查询一下当前使用的安装的node版本,然后使用node use 版 ...