题解 P4314 CPU 监控

传送门

区间加/区间覆盖/区间历史最值的板子题

考虑合并加法标记队列:

his_mx[v]=max(his_mx[v], mx[v]+his_add[u]);
his_add[v]=max(his_add[v], add[v]+his_add[u]);
mx[v]+=add[u]; add[v]+=add[u];

加入赋值标记怎么做呢?
发现一个节点一旦有了赋值标记,整个节点的值就都一样了
那么后面的加法操作可以全部看成赋值操作
合并和上面类似,需要讨论是在合并哪两种标记
复杂度 \(O(n\log n)\)

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f3f3f3f3f
#define N 100010
#define ll long long
//#define int long long

int n, m;
int a[N];
char op[10];
bool is_cov[N<<2];
int tl[N<<2], tr[N<<2];
ll mx[N<<2], his_mx[N<<2], add[N<<2], his_add[N<<2], cov[N<<2], his_cov[N<<2];
#define tl(p) tl[p]
#define tr(p) tr[p]
void pushup(int p) {
	mx[p]=max(mx[p<<1], mx[p<<1|1]);
	his_mx[p]=max(his_mx[p<<1], his_mx[p<<1|1]);
}
void spread_cov(int p, ll val, ll his_val) {
	if (!is_cov[p]) his_cov[p]=his_val, is_cov[p]=1;
	mx[p]=cov[p]=val;
	his_cov[p]=max(his_cov[p], his_val);
	his_mx[p]=max(his_mx[p], his_cov[p]);
}
void spread_add(int p, ll val, ll his_val) {
	// cout<<"spread_add: "<<p<<' '<<val<<' '<<his_val<<endl;
	if (is_cov[p]) spread_cov(p, cov[p]+val, cov[p]+his_val);
	else {
		his_mx[p]=max(his_mx[p], mx[p]+his_val);
		his_add[p]=max(his_add[p], add[p]+his_val);
		mx[p]+=val; add[p]+=val;
	}
}
void spread(int p) {
	spread_add(p<<1, add[p], his_add[p]);
	if (is_cov[p]) spread_cov(p<<1, cov[p], his_cov[p]);
	spread_add(p<<1|1, add[p], his_add[p]);
	if (is_cov[p]) spread_cov(p<<1|1, cov[p], his_cov[p]);
	add[p]=his_add[p]=0; is_cov[p]=0;
}
void build(int p, int l, int r) {
	tl(p)=l; tr(p)=r;
	if (l==r) {mx[p]=his_mx[p]=a[l]; return ;}
	int mid=(l+r)>>1;
	build(p<<1, l, mid);
	build(p<<1|1, mid+1, r);
	pushup(p);
}
void upd(int p, int l, int r, ll val) {
	if (l<=tl(p)&&r>=tr(p)) {
		mx[p]+=val; his_mx[p]=max(his_mx[p], mx[p]);
		if (is_cov[p]) cov[p]+=val, his_cov[p]=max(his_cov[p], cov[p]);
		else add[p]+=val, his_add[p]=max(his_add[p], add[p]);
		return ;
	}
	spread(p);
	int mid=(tl(p)+tr(p))>>1;
	if (l<=mid) upd(p<<1, l, r, val);
	if (r>mid) upd(p<<1|1, l, r, val);
	pushup(p);
}
void cover(int p, int l, int r, ll val) {
	if (l<=tl(p)&&r>=tr(p)) {
		mx[p]=val; his_mx[p]=max(his_mx[p], mx[p]);
		if (is_cov[p]) cov[p]=val, his_cov[p]=max(his_cov[p], cov[p]);
		else is_cov[p]=1, cov[p]=his_cov[p]=val;
		return ;
	}
	spread(p);
	int mid=(tl(p)+tr(p))>>1;
	if (l<=mid) cover(p<<1, l, r, val);
	if (r>mid) cover(p<<1|1, l, r, val);
	pushup(p);
}
ll qmax(int p, int l, int r) {
	if (l<=tl(p)&&r>=tr(p)) return mx[p];
	spread(p);
	int mid=(tl(p)+tr(p))>>1; ll ans=-INF;
	if (l<=mid) ans=max(ans, qmax(p<<1, l, r));
	if (r>mid) ans=max(ans, qmax(p<<1|1, l, r));
	return ans;
}
ll qhis(int p, int l, int r) {
	if (l<=tl(p)&&r>=tr(p)) return his_mx[p];
	spread(p);
	int mid=(tl(p)+tr(p))>>1; ll ans=-INF;
	if (l<=mid) ans=max(ans, qhis(p<<1, l, r));
	if (r>mid) ans=max(ans, qhis(p<<1|1, l, r));
	return ans;
}

signed main()
{
	scanf("%d", &n);
	for (int i=1; i<=n; ++i) scanf("%d", &a[i]);
	build(1, 1, n);
	scanf("%d", &m);
	for (int i=1,x,y,z; i<=m; ++i) {
		scanf("%s%d%d", op, &x, &y);
		if (*op=='Q') printf("%lld\n", qmax(1, x, y));
		else if (*op=='A') printf("%lld\n", qhis(1, x, y));
		else if (*op=='P') {
			scanf("%d", &z);
			upd(1, x, y, z);
		}
		else {
			scanf("%d", &z);
			cover(1, x, y, z);
		}
	}

	return 0;
}
posted @ 2022-03-31 18:12  Administrator-09  阅读(0)  评论(0编辑  收藏  举报