题解 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;
}