[bzoj3064] [Tyvj 1518] CPU监控

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

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

Solution

论文题就是强大QAQ

考虑把区间覆盖转化成区间取(max),标记记成二元组((x,y)),表示先区间加上(x),再对(y)(max),也就是(a_i=max(a_i+x,y))

那么区间加标记就是((x,-infty)),区间覆盖就是((-infty,x))

然后对于每个点记两个标记(now)(history),表示当前标记和历史最大标记。

那么对于当前标记,将((c,d))((a,b))上合并,显然结果是((a+c,max(b+c,d)))

对于历史最大标记,标记((a,b))可以看成是一个形如(y=max(x+a,b))的函数,显然这是个分段函数,第一段是(y=b),第二段是(y=x+a),两个标记合并对于每个(x)都是要取最大值,所以取函数最上面那一段,标记((a,b))((c,d))合并的结果就是((max(a,c),max(b,d)))

然后具体看代码吧,(我能说我因为fread挂了而T了一版吗QAQ)

#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;

namespace fast_IO {
	template <typename T> inline void read(T &x) {
		x=0;T f=1;char ch=getchar();
		for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
		for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
	}
	template <typename T,typename... Args> inline void read(T& x,Args& ...args) {
		read(x),read(args...);
	}

	char buf2[1<<21],a[80];int p,p3=-1;

	inline void flush() {fwrite(buf2,1,p3+1,stdout),p3=-1;}
	template <typename T> inline void write(T x) {
		if(p3>(1<<20)) flush();
		if(x<0) buf2[++p3]='-',x=-x;
		do {a[++p]=x%10+48;} while(x/=10);
		do {buf2[++p3]=a[p];} while(--p);
		buf2[++p3]='
';
	}
	template <typename T,typename... Args> inline void write(T x,Args ...args) {
		write(x),write(args...);
	}
}

using fast_IO :: read;
using fast_IO :: write;
using fast_IO :: flush;

const int maxn = 1e5+10;
const int inf = 0x3f3f3f3f;

int n,m,val[maxn];
char s[10];

#define ls p<<1
#define rs p<<1|1
#define mid ((l+r)>>1)

struct Segment_Tree {
	int hmax[maxn<<2],nmax[maxn<<2];
	struct tag {
		int add,mx;
		inline void init() {add=0,mx=-inf;}
		inline tag operator + (const tag &rhs) const {return (tag){max(-inf,add+rhs.add),max(mx+rhs.add,rhs.mx)};}
		inline tag operator * (const tag &rhs) const {return (tag){max(add,rhs.add),max(mx,rhs.mx)};}
	}nlazy[maxn<<2],hlazy[maxn<<2];
	inline void update(int p) {
		hmax[p]=max(hmax[ls],hmax[rs]);
		nmax[p]=max(nmax[ls],nmax[rs]);
	}
	inline void push_tag(int p,tag now,tag history) {
		hlazy[p]=hlazy[p]*(nlazy[p]+history);
		nlazy[p]=nlazy[p]+now;
		hmax[p]=max(hmax[p],max(nmax[p]+history.add,history.mx));
		nmax[p]=max(nmax[p]+now.add,now.mx);
	}
	inline void pushdown(int p) {
		push_tag(ls,nlazy[p],hlazy[p]);
		push_tag(rs,nlazy[p],hlazy[p]);
		nlazy[p].init(),hlazy[p].init();
	}
	void modify(int p,int l,int r,int x,int y,int add,int mx) {
		if(x<=l&&r<=y) return push_tag(p,(tag){add,mx},(tag){add,mx}),void();
		pushdown(p);
		if(x<=mid) modify(ls,l,mid,x,y,add,mx);
		if(y>mid) modify(rs,mid+1,r,x,y,add,mx);
		update(p);
	}
	int query_hmax(int p,int l,int r,int x,int y) {
		if(x<=l&&r<=y) return hmax[p];
		int ans=-inf;pushdown(p);
		if(x<=mid) ans=max(ans,query_hmax(ls,l,mid,x,y));
		if(y>mid) ans=max(ans,query_hmax(rs,mid+1,r,x,y));
		return ans;		
	}
	int query_nmax(int p,int l,int r,int x,int y) {
		if(x<=l&&r<=y) return nmax[p];
		int ans=-inf;pushdown(p);
		if(x<=mid) ans=max(ans,query_nmax(ls,l,mid,x,y));
		if(y>mid) ans=max(ans,query_nmax(rs,mid+1,r,x,y));
		return ans;		
	}
	void build(int p,int l,int r) {
		hlazy[p].init(),nlazy[p].init();
		if(l==r) return hmax[p]=nmax[p]=val[l],void();
		build(ls,l,mid),build(rs,mid+1,r),update(p);
	}
}SGT;

#undef ls
#undef rs
#undef mid

int main() {
	read(n);
	for(int i=1;i<=n;i++) read(val[i]);
	SGT.build(1,1,n);
	read(m);
	for(int i=1;i<=m;i++) {
		scanf("%s",s+1);int x,y,z;read(x,y);
		if(s[1]=='Q') write(SGT.query_nmax(1,1,n,x,y));
		else if(s[1]=='A') write(SGT.query_hmax(1,1,n,x,y));
		else if(s[1]=='P') read(z),SGT.modify(1,1,n,x,y,z,-inf);
		else read(z),SGT.modify(1,1,n,x,y,-inf,z);
	}
	flush();
	return 0;
}
原文地址:https://www.cnblogs.com/hbyer/p/10225233.html