【BZOJ3064】CPU监控(线段树)

【BZOJ3064】CPU监控(线段树)

题面

BZOJ
洛谷

题解

神仙\(zsy\)出在了\(noip\)模拟的题目。(然而\(zsy\)出的还是这题的升级版)
首先明确一点,这题是一个吉司机线段树。
如果只有区间加法,区间赋值,区间最大值,那么这题很简单。
但是加上了一个区间历史最值,这就很烦了。
于是我们就有了一个神仙做法,
定义一个表示\((a,b)\)表示区间内所有数先\(+a\)再和\(b\)\(max\),即\(x=max(x+a,b)\)
那么这样一来,区间加法转化成\((a,-\infty)\),区间赋值变成了\((-\infty,b)\)
考虑如何合并标记,现在有两个标记\((a,b),(x,y)\),将后者合并到前者上去。
那么可以将标记转化成\((a+x,max(b+x,y))\),原因就是注意一下\(max\)和加法的先后顺序。
对于两个标记如何合并\(max\),是\((max(a,x),max(b,y))\)。原因就是我们可以把这个标记看做是一个分段函数,那么这个合并就比较显然了。

回到题目。
这题到底在干什么呢?
首先对于维护当前值,这个东西是非常显然的。
考虑如何维护一个历史最值,我们对于每个点额外维护一个历史最值的标记,每次覆盖的时候不会覆盖掉历史最值的标记,只会用\(max\)操作更新历史最值标记。
这样子似乎就可以做了。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define MAX 100100
#define lson (now<<1)
#define rson (now<<1|1)
#define inf 1050000000
inline int read()
{
	int x=0;bool t=false;char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	if(ch=='-')t=true,ch=getchar();
	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
	return t?-x:x;
}
struct Data
{
	int a,b;
	void clear(){a=0;b=-inf;}
	int calc(int x){return max(a+x,b);}
}mxt[MAX<<2],tag[MAX<<2];
int mx[MAX<<2],nw[MAX<<2];
Data max(Data a,Data b){return (Data){max(a.a,b.a),max(a.b,b.b)};}
Data operator+(Data a,Data b){return (Data){max(-inf,a.a+b.a),max(a.b+b.a,b.b)};}
void pushup(int now)
{
	nw[now]=max(nw[lson],nw[rson]);
	mx[now]=max(mx[lson],mx[rson]);
}
void puttag(int now,Data a,Data b)
{
	mxt[now]=max(mxt[now],tag[now]+b);
	tag[now]=tag[now]+a;
	mx[now]=max(mx[now],b.calc(nw[now]));
	nw[now]=a.calc(nw[now]);
}
void pushdown(int now)
{
	puttag(lson,tag[now],mxt[now]);
	puttag(rson,tag[now],mxt[now]);
	mxt[now].clear();tag[now].clear();
}
void Build(int now,int l,int r)
{
	tag[now].clear();mxt[now].clear();
	if(l==r){nw[now]=mx[now]=read();return;}
	int mid=(l+r)>>1;
	Build(lson,l,mid);Build(rson,mid+1,r);
	pushup(now);
}
void Modify(int now,int l,int r,int L,int R,Data a)
{
	if(L<=l&&r<=R){puttag(now,a,a);return;}
	int mid=(l+r)>>1;pushdown(now);
	if(L<=mid)Modify(lson,l,mid,L,R,a);
	if(R>mid)Modify(rson,mid+1,r,L,R,a);
	pushup(now);
}
int Query(int now,int l,int r,int L,int R,int opt)
{
	if(L==l&&r==R)return opt?mx[now]:nw[now];
	int mid=(l+r)>>1;pushdown(now);
	if(R<=mid)return Query(lson,l,mid,L,R,opt);
	if(L>mid)return Query(rson,mid+1,r,L,R,opt);
	return max(Query(lson,l,mid,L,mid,opt),Query(rson,mid+1,r,mid+1,R,opt));
}
int n,m;
char ch[20];
int main()
{
	n=read();Build(1,1,n);m=read();
	while(m--)
	{
		scanf("%s",ch);
		int l=read(),r=read();Data a=(Data){-inf,-inf};
		if(ch[0]=='Q')printf("%d\n",Query(1,1,n,l,r,0));
		else if(ch[0]=='A')printf("%d\n",Query(1,1,n,l,r,1));
		else if(ch[0]=='P')a.a=read(),Modify(1,1,n,l,r,a);
		else a.b=read(),Modify(1,1,n,l,r,a);
	}
	return 0;
}

posted @ 2018-08-28 21:44  小蒟蒻yyb  阅读(497)  评论(0编辑  收藏  举报