(居然)比想象中好写多了
操作:
区间赋值,区间加,区间减,区间和
0
0
0取
m
a
x
max
max,单点询问,单点求历史最大值。
此题所有的修改都可以用一个标记表达:
(
a
,
b
)
(a,b)
(a,b)表示将
x
x
x变为
m
a
x
(
a
+
x
,
b
)
max(a+x,b)
max(a+x,b)
那么标记的合并可以发现
(
a
,
b
)
∗
(
c
,
d
)
=
(
a
+
c
,
m
a
x
(
b
+
c
,
d
)
)
(a,b)*(c,d)=(a+c,max(b+c,d))
(a,b)∗(c,d)=(a+c,max(b+c,d))
发现历史最大值标记也是形如
m
a
x
(
a
+
x
,
b
)
max(a+x,b)
max(a+x,b)的形式。
这时标记需要合并与取
m
a
x
max
max。
A C C o d e \mathrm{AC \ Code} AC Code
#include<bits/stdc++.h>
#define maxn 500005
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define lc u<<1
#define rc u<<1|1
#define LL long long
#define Ct const
#define inf ((LL)1e16)
using namespace std;
char cb[1<<16],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<16,stdin),cs==ct)?0:*cs++)
void read(int &res){
char ch;
for(;!isdigit(ch=getc()););
for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0');
}
int n,m,a[maxn];
struct data{
LL ad,mx;
data(LL ad=0,LL mx=0):ad(ad),mx(mx){}
data operator *(Ct data &B)Ct{ return data(max(ad+B.ad,-inf),max(mx+B.ad,B.mx)); }
data operator +(Ct data &B)Ct{ return data(max(ad,B.ad),max(mx,B.mx)); }
LL cal(){ return max(ad,mx); }
}v1[maxn<<2],vp[maxn<<2];
void dtp(int u,Ct data &A,Ct data &B){
vp[u] = vp[u] + v1[u] * B;
v1[u] = v1[u] * A;
}
void dt(int u){
if(v1[u].ad||v1[u].mx||vp[u].ad||vp[u].mx){
dtp(lc,v1[u],vp[u]);
dtp(rc,v1[u],vp[u]);
v1[u]=vp[u]=data(0,0);
}
}
void Build(int u,int l,int r){
if(l==r) return (void)(v1[u]=vp[u]=data(a[l],0));
int m=l+r>>1;Build(lc,l,m),Build(rc,m+1,r);
}
void add(int u,int l,int r,int ql,int qr,Ct data &A){
if(l>qr||ql>r) return;
if(ql<=l&&r<=qr) return (void)(dtp(u,A,A));
int m=l+r>>1;dt(u),add(lc,l,m,ql,qr,A),add(rc,m+1,r,ql,qr,A);
}
void qry(int u,int l,int r,int p,int t){
if(l==r) return (void)(printf("%lld\n",t?vp[u].cal():v1[u].cal()));
int m=l+r>>1;dt(u),p<=m?qry(lc,l,m,p,t):qry(rc,m+1,r,p,t);
}
int main(){
#if not ONLINE_JUDGE
freopen("1.in","r",stdin);
#endif
read(n),read(m);
rep(i,1,n) read(a[i]);
Build(1,1,n);
for(int op,l,r,x;m--;){
read(op),read(l);
if(op <= 3){
read(r),read(x);
if(op == 1) add(1,1,n,l,r,data(x,0));
else if(op == 2) add(1,1,n,l,r,data(-x,0));
else add(1,1,n,l,r,data(-inf,x));
}
else if(op == 4) qry(1,1,n,l,0);
else qry(1,1,n,l,1);
}
}