3064: Tyvj 1518 CPU监控

来源:互联网 发布:清华java培训 编辑:程序博客网 时间:2024/05/16 01:47

3064: Tyvj 1518 CPU监控

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 747  Solved: 292
[Submit][Status][Discuss]

Description

Bob需要一个程序来监视CPU使用率。这是一个很繁琐的过程,为了让问题更加简单,Bob会慢慢列出今天会在用计算机时做什么事。 
Bob会干很多事,除了跑暴力程序看视频之外,还会做出去玩玩和用鼠标乱点之类的事,甚至会一脚踢掉电源……这些事有的会让做这件事的这段时间内CPU使用率增加或减少一个值;有的事还会直接让CPU使用率变为一个值。 
当然Bob会询问:在之前给出的事件影响下,CPU在某段时间内,使用率最高是多少。有时候Bob还会好奇地询问,在某段时间内CPU曾经的最高使用率是多少。 
为了使计算精确,使用率不用百分比而用一个整数表示。 
不保证Bob的事件列表出了莫名的问题,使得使用率为负……………… 

Input

第一行一个正整数T,表示Bob需要监视CPU的总时间。 
然后第二行给出T个数表示在你的监视程序执行之前,Bob干的事让CPU在这段时间内每个时刻的使用率达已经达到了多少。 
第三行给出一个数E,表示Bob需要做的事和询问的总数。 
接下来E行每行表示给出一个询问或者列出一条事件: 
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 
时间的单位为秒,使用率没有单位。 
X和Y均为正整数(X<=Y),Z为一个整数。 
从X到Y这段时间包含第X秒和第Y秒。 
保证必要运算在有符号32位整数以内。 

Output

对于每个询问,输出一行一个整数回答。 

Sample Input

10
-62 -83 -9 -70 79 -78 -31 40 -18 -5
20
A 2 7
A 4 4
Q 4 4
P 2 2 -74
P 7 9 -71
P 7 10 -8
A 10 10
A 5 9
C 1 8 10
Q 6 6
Q 8 10
A 1 7
P 9 9 96
A 5 5
P 8 10 -53
P 6 6 5
A 10 10
A 4 4
Q 1 5
P 4 9 -69

Sample Output

79
-70
-70
-5
79
10
10
79
79
-5
10
10

HINT

 数据分布如下: 

第1、2个数据保证T和E均小于等于1000 

第3、4个数据保证只有Q类询问 

第5、6个数据保证只有C类事件 

第7、8个数据保证只有P类事件 

全部数据保证T和E均小于等于100000 

Source

[Submit][Status][Discuss]

几乎花了半天时间来调这一题,,整个人都不太好了。。。。。。
简明题意,,给一个数组,要求支持:
1.询问区间最值
2.询问区间历史最值(即这个区间历史上出现过的最大值)
3.区间加减
4.区间覆盖
显然是要用线段树做,,具体做法见吉如一的论文(话说这居然属于最简单的一类?!),此处补一点笔记
线段树上每个点维护:
A[o]:当前最值,B[o]:历史最值,Add[o]:加法懒惰标记 
Pa[o]:历史加法最值,Mark[o]:区间覆盖标记,Pm[o]:历史覆盖最值
先不考虑区间覆盖操作,,区间加法会在线段树上定位log个区间,对于这些区间,Add[o]的维护十分容易
定义Pa[o]就是历史上在该点打下的标记中,累计最大的时刻的标记和
比如,有一系列的P操作同时作用于该点,,+7 +9 -2 +6 -5
那么Pa[o] = 20,也就是第四次操作后的结果,因为这次是5次里累计最大的
考虑标记下传,Pa[son] = max(Pa[son],Add[son] + Pa[o]),Add[son] += Add[o]
为什么这样做是对的??在打标记的时候,儿子出现了更早的标记,那么说明对儿子的操作都是之前完成了的
对于之前的最优结果,Pa[son]已经储存,如果要知道能不能更优,当然是之前的操作和 + 当前的最优决策
这样,对于不存在覆盖操作的简易版已经解决

接下来,增添覆盖操作,对于一个节点,如果在这里打过一个覆盖标记,
那么,之后如果再操作这个节点,无论是操作3还是操作4,都和区间覆盖无异
因此,在打标记的时候特判该点有无Mark标记,如果有,直接对Mark和Pm更新,对于操作3,转化一下就行
这种情况要一直持续到下次把这个点的标记下传掉
综上,每次下传标记,有B[o] = max{B[o],max(A[o] + Pa[o],Pm[o])}
即先考虑第一阶段++--能取得的最优结果,在考虑第二阶段被反复覆盖能取得的最优结果

但是,,写起来简直是WA飞。。。。。
一开始给Add标记赋的居然是-INF而不是0。。。
然后,,下传标记的时候儿子还要特判是否被Mark过,否则特殊处理
最后,,Mark的修改时强行变更,,作死取max???
#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>#include<cstring>#include<vector>#include<queue>#include<set>#include<map>#include<stack>#include<bitset>#include<ext/pb_ds/priority_queue.hpp>using namespace std;const int maxn = 1E5 + 10;const int T = 4;typedef long long LL;const LL INF = 1E16;const char com[4] = {'Q','A','P','C'};int n,m;LL A[maxn*T],B[maxn*T],Add[maxn*T],Pa[maxn*T],Mark[maxn*T],Pm[maxn*T];int getint(){char ch = getchar(); int ret = 0,a = 1;while (ch < '0' || '9' < ch){if (ch == '-') a = -1;ch = getchar();}while ('0' <= ch && ch <= '9')ret = ret*10 + ch - '0',ch = getchar();return ret * a;}void Clear(int o) {Add[o] = Pa[o] = 0;Mark[o] = Pm[o] = -INF;}void maintain(int o){int lc = (o<<1),rc = (o<<1|1);A[o] = max(A[lc],A[rc]);B[o] = max(B[lc],B[rc]);}void Down(int o,LL AD,LL P){if (Pm[o] != -INF) Pm[o] = max(Pm[o],Mark[o] + P),Mark[o] += AD;else Pa[o] = max(Pa[o],Add[o] + P),Add[o] += AD;}void pushdown(int o,int l,int r){if (Add[o] == 0 && Mark[o] == -INF) return;B[o] = max(B[o],max(A[o] + Pa[o],Pm[o]));int lc = (o<<1),rc = (o<<1|1),mid = (l + r) >> 1;if (Add[o] != 0){A[o] += Add[o];if (l < r) Down(lc,Add[o],Pa[o]),Down(rc,Add[o],Pa[o]);}if (Mark[o] != -INF){A[o] = Mark[o];if (l < r){Mark[lc] = Mark[rc] = Mark[o];Pm[lc] = max(Pm[lc],Pm[o]);Pm[rc] = max(Pm[rc],Pm[o]);}}Clear(o);}void Build(int o,int l,int r){if (l == r){Clear(o); A[o] = B[o] = getint(); return;}int mid = (l + r) >> 1; Clear(o);Build(o<<1,l,mid); Build(o<<1|1,mid+1,r);maintain(o);}void Modify(int o,int l,int r,int ml,int mr,LL k,int typ){if (ml <= l && r <= mr){if (typ == 2){if (Pm[o] != -INF) Mark[o] += k,Pm[o] = max(Pm[o],Mark[o]);else Add[o] += k,Pa[o] = max(Pa[o],Add[o]);}else Mark[o] = k,Pm[o] = max(Pm[o],k);pushdown(o,l,r); return;}int mid = (l + r) >> 1; pushdown(o,l,r);if (ml <= mid) Modify(o<<1,l,mid,ml,mr,k,typ); else pushdown(o<<1,l,mid);if (mr > mid) Modify(o<<1|1,mid+1,r,ml,mr,k,typ); else pushdown(o<<1|1,mid+1,r);maintain(o);}LL Query(int o,int l,int r,int ql,int qr,int typ){pushdown(o,l,r);if (ql <= l && r <= qr) return !typ? A[o] : B[o];int mid = (l + r) >> 1; LL ret = -INF;if (ql <= mid) ret = Query(o<<1,l,mid,ql,qr,typ);if (qr > mid) ret = max(ret,Query(o<<1|1,mid+1,r,ql,qr,typ));return ret;}int getcom(){char ch = getchar();for (;;){for (int i = 0; i < 4; i++)if (ch == com[i]) return i;ch = getchar();}}int main(){#ifdef DMCfreopen("DMC.txt","r",stdin);#endifn = getint(); Build(1,1,n); m = getint();while (m--){int typ = getcom(),l,r;l = getint(); r = getint();if (typ == 0) printf("%lld\n",Query(1,1,n,l,r,0));else if (typ == 1) printf("%lld\n",Query(1,1,n,l,r,1));else if (typ == 2) Modify(1,1,n,l,r,getint(),2);else Modify(1,1,n,l,r,getint(),3);}return 0;}

0 0
原创粉丝点击