详见吉丽的集训队论文
这里实现我把最大值和标记合并在一起了
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
const int N=1000005;
int maxv[N<<2],sec[N<<2],cnt[N<<2]; ll sum[N<<2];
int n,a[N];
inline void update(int x){
int l=x<<1,r=x<<1|1;
sum[x]=sum[l]+sum[r];
if (maxv[l]==maxv[r])
maxv[x]=maxv[l],cnt[x]=cnt[l]+cnt[r],sec[x]=max(sec[l],sec[r]);
else{ // r>l
if (maxv[l]>maxv[r]) swap(l,r);
maxv[x]=maxv[r]; cnt[x]=cnt[r];
sec[x]=max(sec[r],maxv[l]);
}
}
inline void push(int x,int t){
if (sec[x]<t && t<=maxv[x])
sum[x]-=(ll)(maxv[x]-t)*cnt[x],maxv[x]=t;
}
inline void Build(int x,int l,int r){
if (l==r){
maxv[x]=a[l]; cnt[x]=1; sec[x]=-1; sum[x]=a[l];
return;
}
int mid=(l+r)>>1;
Build(x<<1,l,mid); Build(x<<1|1,mid+1,r);
update(x);
}
inline void Modify(int x,int l,int r,int ql,int qr,int qt){
if (ql<=l && r<=qr && qt>sec[x]){
push(x,qt);
return;
}
int mid=(l+r)>>1; push(x<<1,maxv[x]),push(x<<1|1,maxv[x]);
if (ql<=mid) Modify(x<<1,l,mid,ql,qr,qt);
if (qr>mid) Modify(x<<1|1,mid+1,r,ql,qr,qt);
update(x);
}
inline ll Sum(int x,int l,int r,int ql,int qr){
if (ql<=l && r<=qr) return sum[x];
ll ret=0; int mid=(l+r)>>1; push(x<<1,maxv[x]),push(x<<1|1,maxv[x]);
if (ql<=mid) ret+=Sum(x<<1,l,mid,ql,qr);
if (qr>mid) ret+=Sum(x<<1|1,mid+1,r,ql,qr);
return ret;
}
inline int Max(int x,int l,int r,int ql,int qr){
if (ql<=l && r<=qr) return maxv[x];
int ret=0; int mid=(l+r)>>1; push(x<<1,maxv[x]),push(x<<1|1,maxv[x]);
if (ql<=mid) ret=max(ret,Max(x<<1,l,mid,ql,qr));
if (qr>mid) ret=max(ret,Max(x<<1|1,mid+1,r,ql,qr));
return ret;
}
int main(){
int T,Q,l,r,t,order;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(T);
while (T--){
read(n); read(Q);
for (int i=1;i<=n;i++) read(a[i]);
Build(1,1,n);
while (Q--){
read(order); read(l); read(r);
if (order==0)
read(t),Modify(1,1,n,l,r,t);
else if (order==1)
printf("%d\n",Max(1,1,n,l,r));
else
printf("%I64d\n",Sum(1,1,n,l,r));
}
}
return 0;
}