P4314 CPU监控 题解

发布于 2022年 05月 19日 18:32

题面

历史最值线段树。考虑到每个区间的操作大概是这样:先是一些加法操作,然后有一次赋值,在这次赋值之后所有的操作都可以表示成赋值。所以维护两类标记,一类表示前面的加法,另一类表示赋值,记录一下这个点有没有开始赋值即可。代码及其难调,建议理清思路再写……

点击查看代码
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const int N=1e5+13;
const ll INF=0x3f3f3f3f3f3f3f3fll;
inline ll max(const ll &a,const ll &b){return a>b?a:b;}
int n,a[N],m;
struct SegTree{int l,r;ll add,preadd,max,premax,set,preset;bool state;}t[N<<2];
#define ls p<<1
#define rs p<<1|1
#define mid ((t[p].l+t[p].r)>>1)
inline void refresh(int p){
	t[p].max=max(t[ls].max,t[rs].max);
	t[p].premax=max(t[ls].premax,t[rs].premax);
}
void build(int p,int l,int r){
	t[p].l=l,t[p].r=r,t[p].max=t[p].premax=-INF;
	if(l==r){t[p].max=t[p].premax=a[l];return;}
	build(ls,l,mid);build(rs,mid+1,r);
	refresh(p);
}
inline void pushup_set(int p,ll x,ll px){
	if(!t[p].state){
		t[p].state=1;
		t[p].preset=px;
		t[p].premax=max(t[p].premax,px);	
	}
	else{
		t[p].preset=max(t[p].preset,px);
		t[p].premax=max(t[p].premax,px);
	}
	t[p].set=t[p].max=x;
}
inline void pushup_add(int p,ll x,ll px){
	if(t[p].state){
		t[p].preset=max(t[p].preset,t[p].set+px);
		t[p].premax=max(t[p].premax,t[p].max+px);
		t[p].set+=x,t[p].max+=x;
	}
	else{
		t[p].preadd=max(t[p].preadd,t[p].add+px);
		t[p].premax=max(t[p].premax,t[p].max+px);
		t[p].add+=x,t[p].max+=x;
	}
}
inline void pushdown(int p){
	pushup_add(ls,t[p].add,t[p].preadd);
	pushup_add(rs,t[p].add,t[p].preadd);
	t[p].add=t[p].preadd=0;
	if(t[p].state){
		pushup_set(ls,t[p].set,t[p].preset);
		pushup_set(rs,t[p].set,t[p].preset);
		t[p].state=0,t[p].set=t[p].preset=0;
	}
}
void update(int p,int l,int r,ll x){
	if(l<=t[p].l&&t[p].r<=r) return pushup_add(p,x,x);
	pushdown(p);
	if(l<=mid) update(ls,l,r,x);
	if(r>mid) update(rs,l,r,x);
	refresh(p);
}
void modify(int p,int l,int r,ll x){
	if(l<=t[p].l&&t[p].r<=r) return pushup_set(p,x,x);
	pushdown(p);
	if(l<=mid) modify(ls,l,r,x);
	if(r>mid) modify(rs,l,r,x);
	refresh(p);
}
ll query_max(int p,int l,int r){
	if(l<=t[p].l&&t[p].r<=r) return t[p].max;
	pushdown(p);ll res=-INF;
	if(l<=mid) res=max(res,query_max(ls,l,r));
	if(r>mid) res=max(res,query_max(rs,l,r));
	return res;
}
ll query_pre(int p,int l,int r){
	if(l<=t[p].l&&t[p].r<=r) return t[p].premax;
	pushdown(p);ll res=-INF;
	if(l<=mid) res=max(res,query_pre(ls,l,r));
	if(r>mid) res=max(res,query_pre(rs,l,r));
	return res;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i) scanf("%d",&a[i]);
	build(1,1,n);
	scanf("%d",&m);
	while(m--){
		char op[2];int x,y,z;
		scanf("%s%d%d",op,&x,&y);
		switch(op[0]){
			case 'Q':printf("%lld\n",query_max(1,x,y));break;
			case 'A':printf("%lld\n",query_pre(1,x,y));break;
			case 'P':scanf("%d",&z);update(1,x,y,z);break;
			case 'C':scanf("%d",&z);modify(1,x,y,z);break;
		}
	}
	return 0;
}

推荐文章