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监控 线段树裸题的更多相关文章

  1. POJ 3468 线段树裸题

    这些天一直在看线段树,因为临近期末,所以看得断断续续,弄得有些知识点没能理解得很透切,但我也知道不能钻牛角尖,所以配合着刷题来加深理解. 然后,这是线段树裸题,而且是最简单的区间增加与查询,我参考了A ...

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

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

  3. BZOJ1067&P2471 [SCOI2007]降雨量[线段树裸题+细节注意]

    dlntqlwsl 很裸的一道线段树题,被硬生生刷成了紫题..可能因为细节问题吧,我也栽了一次WA50分.不过这个隐藏条件真的对本菜鸡来说不易发现啊. 未知的年份连续的就看成一个就好了,把年份都离散化 ...

  4. 【LOJ6029】「雅礼集训 2017 Day1」市场(线段树裸题)

    点此看题面 大致题意: 维护序列,支持区间加法,区间除法(向下取整),区间求\(min\)和区间求和. 线段树维护区间除法 区间加法.区间求\(min\)和区间求和都是线段树基本操作,因此略过不提. ...

  5. BZOJ.3064.CPU监控(线段树 历史最值)

    题目链接 \(Description\) 有一个长为n的序列Ai,要求支持查询[l,r]的最值.历史最值,区间加/重设 \(Solution\) 线段树,每个点再维护一个历史(从0到现在)最大值.历史 ...

  6. HDU1166 线段树裸题 区间求和

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  7. HDU 4893 线段树裸题

    Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Oth ...

  8. cdoj 1324 卿学姐与公主 线段树裸题

    卿学姐与公主 Time Limit: 2000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit St ...

  9. BZOJ3064 Tyvj 1518 CPU监控 线段树

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3064 题意概括 一个序列,要你支持以下操作: 1. 区间询问最大值 2. 区间询问历史最大值 3. ...

随机推荐

  1. 数组中出现次数超过一半的数字(剑指offer-28)

    题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. ...

  2. PE文件格式详解(八)

    0x00 前言 前面了解了PE文件的输入和输出,今天来看看另一个重要的结构——资源.资源结构是很典型的树形结构,层层查找,最终找到资源位置. 0x01 资源结构介绍 Windows程序的各种界面成为资 ...

  3. docker入门、LXC、windows container 和 Hyper知识基础、实用情况

    虚拟机与容器 很明显可以看出两者在操作系统级别上的隔离和进程上的隔离的区别,VM因为隔离级别更高明显更重. linux容器主要技术特点: 文件系统隔离:每个容器都有自己的root文件系统 进程隔离:每 ...

  4. WPF 设置帧率

    开始仔细学习WPF了 说是动画不流畅,可以通过设置帧率解决,查了很多,都说设置Timeline.DesiredFrameRateProperty, 但都没说加到哪里,在代码很多地方加上了,统统无效.最 ...

  5. Python List comprehension列表推导式

    http://blog.chinaunix.net/uid-28631822-id-3488324.html 具体内容需要进一步学习

  6. 数据可视化之powerBI技巧(十七)在Power BI中对数据进行分组

    根据某一个维度的数据,进行分组统计,是很常见的做法,比如按年龄对客户进行分组,按考试成绩进行分组统计等,这篇文章介绍一下,在PowerBI中如何对数据进行分组. 在PowerQuery编辑器中分组 在 ...

  7. css换行后缩进,css缩进技巧

    一般情况下像下图这样需要缩进的,一般都会外面一个div里面两块需要两个div然后用定位或者flex.table.浮动后设置宽度等来实现 已知宽度的情况下上面列的方法都适用 不知宽度的情况下可以用fle ...

  8. iis 0x80070032 Cannot read configuration file because it exceeds the maximum file size

    问题:iis部署了网站,由于webconfig文件过大(251kb,默认250kb)导致网站报错 0x80070032 Cannot read configuration file because i ...

  9. linux 安装 mysql8

    1. 下载地址: https://dev.mysql.com/downloads/file/?id=484922 2. 安装 mysql80-community-release-el7-3.noarc ...

  10. CSS栅格布局

    CSS栅格布局 认识栅格布局 CSS的栅格布局也被称为网格布局(Grid Layout),它是一种新兴的布局方式. 栅格布局是一个二维系统,这意味着它可以同时处理列和行,与弹性布局相似,栅格系统也是由 ...