[bzoj3064]Tyvj 1518 CPU监控 线段树&排行榜垫底留念

3064: Tyvj 1518 CPU监控

Time Limit: 20 Sec   Memory Limit: 256 MB
[ 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

大家不要鄙视b站倒数第一名喔~,因为我就是垫底的,自带巨大常数
pushdown长过线段树系列,一不小心就会写错
应该可以优化
#include<iostream>
#include<cstdio>
typedef long long ll;
#define inf 1e18
using namespace std;
const int N = 150005;
int n,m,a[N],ls[N*4],rs[N*4],id=0,root; char ch[5];
ll mx[N*4],f1[N*4],f2[N*4],m_x[N*4],f_1[N*4],f_2[N*4];
void update( int k ){
	mx[k] = max(mx[ls[k]],mx[rs[k]]);
	m_x[k] = max(m_x[ls[k]],m_x[rs[k]]);
}
void pushdown( int k ){
	m_x[ls[k]] = max(m_x[ls[k]],max(f_2[k],mx[ls[k]]+f_1[k]));
	if( f2[ls[k]] == -inf ) f_1[ls[k]] = max(f_1[ls[k]],f1[ls[k]]+f_1[k]);
	else f_2[ls[k]] = max(f_2[ls[k]],f2[ls[k]]+f_1[k]);
	if( f1[k] ){
		if( f2[ls[k]] != -inf ) f2[ls[k]] += f1[k];
		else f1[ls[k]] += f1[k];
		mx[ls[k]] += f1[k];
	}
	if( f2[k] != -inf ){
		mx[ls[k]] = f2[ls[k]] = f2[k];
		f1[ls[k]] = 0;
	}
	f_1[ls[k]] = max(f_1[ls[k]],f1[ls[k]]);
	f_2[ls[k]] = max(f_2[ls[k]],max(f2[k],f_2[k]));
//======================================================================================================
	m_x[rs[k]] = max(m_x[rs[k]],max(f_2[k],mx[rs[k]]+f_1[k]));
	if( f2[rs[k]] == -inf ) f_1[rs[k]] = max(f_1[rs[k]],f1[rs[k]]+f_1[k]);
	else f_2[rs[k]] = max(f_2[rs[k]],f2[rs[k]]+f_1[k]);
	if( f1[k] ){
		if( f2[rs[k]] != -inf ) f2[rs[k]] += f1[k];
		else f1[rs[k]] += f1[k];
		mx[rs[k]] += f1[k];
	}
	if( f2[k] != -inf ){
		mx[rs[k]] = f2[rs[k]] = f2[k];
		f1[rs[k]] = 0;
	}
	f_1[rs[k]] = max(f_1[rs[k]],f1[rs[k]]);
	f_2[rs[k]] = max(f_2[rs[k]],max(f2[k],f_2[k]));
//======================================================================================================
	f_1[k] = f1[k] = 0;
	f_2[k] = f2[k] = -inf;
}
void build( int &k, int l, int r ){
	k = ++id; f1[k] = f_1[k] = 0; f2[k] = f_2[k] = -inf;
	if( l == r ){
		mx[k] = m_x[k] = (ll)a[l]; return;
	}
	int mid = (l+r)>>1;
	build(ls[k],l,mid); build(rs[k],mid+1,r);
	update(k);
} 
void change( int k, int l, int r, int L, int R, ll x, int type ){
	if( l != r ) pushdown(k);
	if( L <= l && r <= R ){
		if( !type ) mx[k] += x, f1[k] += x, f_1[k] += x;
		else f2[k] = f_2[k] = mx[k] = x;
		m_x[k] = max(mx[k],m_x[k]);
		return;
	}
	int mid = (l+r)>>1;
	if( mid >= L ) change( ls[k], l, mid, L, R, x, type );
	if( mid < R ) change( rs[k], mid+1, r, L, R, x, type );
	update(k);
}
ll query( int k, int l, int r, int L, int R, int type ){
	if( l != k ) pushdown(k);
	if( L <= l && R >= r ){ return type ? m_x[k] : mx[k]; }
	int mid = (l+r)>>1; ll res = -inf;
	if( mid >= L ) res = max(res,query(ls[k],l,mid,L,R,type));
	if( mid < R ) res = max(res,query(rs[k],mid+1,r,L,R,type));
	return res;
}
int main(){
	scanf("%d",&n);
	for( int i = 1; i <= n; i++ ) scanf("%d", &a[i]);
	build(root,1,n); scanf("%d", &m);
	for( int i = 1,l,r,x; i <= m; i++ ){
		scanf("%s", ch);
		if( ch[0] == 'Q' ){ scanf("%d%d", &l, &r); printf("%lld\n",query(root,1,n,l,r,0));}
		if( ch[0] == 'A' ){ scanf("%d%d", &l, &r); printf("%lld\n",query(root,1,n,l,r,1));}
		if( ch[0] == 'P' ){ scanf("%d%d%d", &l, &r, &x); change(root,1,n,l,r,(ll)x,0);}
		if( ch[0] == 'C' ){ scanf("%d%d%d", &l, &r, &x); change(root,1,n,l,r,(ll)x,1);}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值