Description
维护一个长度为n的序列,资瓷:
- 区间加
- 区间覆盖
- 询问[L,R]内最大值
- 询问[L,R]内历史最大值
Solution
前三个都好说
对于第四个,我们重新定义一个操作v+(a,b)=max(v+a,b),这样操作1就是v+(x,-INF),操作2就是v+(-INF,x)
考虑两个标记的合并,那么就是v+(a,b)+(c,d)=max(max(v+a,b)+c,d)=max(v+a+c,max(b,d))=v+(a+c,max(b,d)),注意这个是有序的
于是乎我们可以分别维护当前最大值和历史最大值,下传标记的时候就合并就可以了
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
const int INF=0x3f3f3f3f;
const int N=200005;
struct data {
int x,y;
data operator +(data b) {return (data) {std:: max(-INF,x+b.x),std:: max(y+b.x,b.y)};}
data operator *(data b) {return (data) {std:: max(x,b.x),std:: max(y,b.y)};}
} ptag[N<<2],ntag[N<<2];
int nmax[N<<2],pmax[N<<2];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void push_up(int now) {
pmax[now]=std:: max(pmax[now<<1],pmax[now<<1|1]);
nmax[now]=std:: max(nmax[now<<1],nmax[now<<1|1]);
}
int calc(int v,data tag) {
return std:: max(tag.x+v,tag.y);
}
void push_down(int now) {
int ls=now<<1,rs=now<<1|1;
ptag[ls]=ptag[ls]*(ntag[ls]+ptag[now]);
ntag[ls]=ntag[ls]+ntag[now];
pmax[ls]=std:: max(pmax[ls],calc(nmax[ls],ptag[now]));
nmax[ls]=calc(nmax[ls],ntag[now]);
ptag[rs]=ptag[rs]*(ntag[rs]+ptag[now]);
ntag[rs]=ntag[rs]+ntag[now];
pmax[rs]=std:: max(pmax[rs],calc(nmax[rs],ptag[now]));
nmax[rs]=calc(nmax[rs],ntag[now]);
ntag[now]=ptag[now]=(data) {0,-INF};
}
void modify(int now,int tl,int tr,int l,int r,data d) {
if (tl>=l&&tr<=r) {
ptag[now]=ptag[now]*(ntag[now]+d);
ntag[now]=ntag[now]+d;
pmax[now]=std:: max(pmax[now],calc(nmax[now],d));
nmax[now]=calc(nmax[now],d);
return ;
}
int mid=(tl+tr)>>1;
push_down(now);
if (l<=mid) modify(now<<1,tl,mid,l,r,d);
if (mid+1<=r) modify(now<<1|1,mid+1,tr,l,r,d);
push_up(now);
}
int query(int now,int tl,int tr,int l,int r,int opt) {
if (tl>=l&&tr<=r) return (!opt)?(nmax[now]):(pmax[now]);
int mid=(tl+tr)>>1,qx=-INF,qy=-INF;
push_down(now);
if (l<=mid) qx=query(now<<1,tl,mid,l,r,opt);
if (mid+1<=r) qy=query(now<<1|1,mid+1,tr,l,r,opt);
return std:: max(qx,qy);
}
void build(int now,int tl,int tr) {
ptag[now]=ntag[now]=(data) {0,-INF};
if (tl==tr) {
nmax[now]=pmax[now]=read();
return ;
}
int mid=(tl+tr)>>1;
build(now<<1,tl,mid);
build(now<<1|1,mid+1,tr);
push_up(now);
}
int main(void) {
freopen("data.in","r",stdin);
freopen("myp.out","w",stdout);
int n=read();
build(1,1,n);
for (int T=read(),l,r,z,ch;T--;) {
for (ch=getchar();ch!='A'&&ch!='P'&&ch!='C'&&ch!='Q';) ch=getchar();
l=read(),r=read();
if (ch=='Q') printf("%d\n", query(1,1,n,l,r,0));
else if (ch=='A') printf("%d\n", query(1,1,n,l,r,1));
else {
z=read();
if (ch=='P') modify(1,1,n,l,r,(data) {z,-INF});
else if (ch=='C') modify(1,1,n,l,r,(data) {-INF,z});
}
}
return 0;
}