rt,虽然define写得多但是都能看懂
#include<bits/stdc++.h>
#define now sgt[p]
#define ls sgt[p<<1]
#define _ls p<<1
#define rs sgt[p<<1|1]
#define _rs p<<1|1
#define getm int m=(now.s+now.t)>>1
typedef long long ll;
using namespace std;
const int maxi=5e5+9;
int N,M,a[maxi],l,r,k,v;
struct node{
ll sum;
int s,t,mxa,cnt,sec,mxb;
int lz1,//LaZy tag of Maximun
lz2,//LaZy tag of Else
lz3,//Maximum of lz1
lz4;//Maximum of lz2
}sgt[maxi<<2];
inline int max(int a,int b){return a>b?a:b;}
inline void output(int p){
cerr<<"p="<<p
<<",sum="<<now.sum
<<",s="<<now.s
<<",t="<<now.t
<<",mxa="<<now.mxa
<<",cnt="<<now.cnt
<<",sec="<<now.sec
<<",mxb="<<now.mxb
<<",lz1="<<now.lz1
<<",lz2="<<now.lz2
<<",lz3="<<now.lz3
<<",lz4="<<now.lz4<<'\n';
}
void debug(int p){
output(p);
if(now.s==now.t)return;
debug(_ls),debug(_rs);
}
inline void update(int p){
now.sum=ls.sum+rs.sum;
//上传区间和
now.mxa=max(ls.mxa,rs.mxa);
now.mxb=max(ls.mxb,rs.mxb);
//上传区间最大值以及区间历史最大值
if(ls.mxa==rs.mxa){
now.sec=max(ls.sec,rs.sec);
now.cnt=ls.cnt+rs.cnt;
}else if(ls.mxa>rs.mxa){
now.sec=max(ls.sec,rs.mxa);
now.cnt=ls.cnt;
}else{
now.sec=max(ls.mxa,rs.sec);
now.cnt=rs.cnt;
}
//分类讨论以计算sec和cnt
return;
}
inline void push(int k1,int k2,int k3,int k4,int p){
//传下来的变量分别是分别对应四个lazy_tag
now.sum+=1ll*k1*now.cnt+1ll*k2*(now.t-now.s+1-now.cnt);
//区间+=区间最大值改变量+区间非最大值改变量
now.mxb=max(now.mxb,now.mxa+k3);
//用 更新前最大值+最大增加量 更新 历史最大值
now.mxa+=k1;
//mxb更新完再更新mxa
if(now.sec!=-INT_MAX)now.sec+=k2;
//若有次大值则用非最大值改变量更新
now.lz3=max(now.lz3,now.lz1+k3);
now.lz4=max(now.lz4,now.lz2+k4);
//用 更新前的改变量+最大增加量 更新lz3和lz4
now.lz1+=k1,now.lz2+=k2;
//更新 最大值和次大值的改变量
return;
}
inline void pushdown(int p){
int mxn=max(ls.mxa,rs.mxa);
if(ls.mxa==mxn){
push(now.lz1,now.lz2,now.lz3,now.lz4,_ls);
}else{
push(now.lz2,now.lz2,now.lz4,now.lz4,_ls);
}
if(rs.mxa==mxn){
push(now.lz1,now.lz2,now.lz3,now.lz4,_ls);
}else{
push(now.lz2,now.lz2,now.lz4,now.lz4,_ls);
}
//若子区间有最大值则用lz1和lz3更新,无则不用
now.lz1=now.lz2=now.lz3=now.lz4=0;
//更新完清零哈
return;
}
void build(int s,int t,int p){
now.s=s,now.t=t;
if(s==t){
now.cnt=1;
now.sum=now.mxa=now.mxb=0ll+a[s];
now.sec=-INT_MAX;
//因为区间可能无次大值故赋极小值
return;
}
int m=(s+t)>>1;
build(s,m,_ls);
build(m+1,t,_rs);
update(p);
return;
}
void _1/*区间加*/(int p){
cerr<<"_1:"<<p<<'\n';
if(l<=now.s&&now.t<=r){
now.sum+=1ll*k*(now.t-now.s+1);
now.mxa+=k;
now.mxb=max(now.mxa,now.mxb);
if(now.sec!=-INT_MAX)now.sec+=k;
now.lz1+=k,now.lz2+=k;
now.lz3=max(now.lz1,now.lz3);
now.lz4=max(now.lz2,now.lz4);
return;
}
pushdown(p);
getm;
if(l<=m)_1(_ls);
if(m<r)_1(_rs);
return;
}
void _2/*区间取min*/(int p){
if(v>=now.mxa)return;
cerr<<"_2:"<<p<<'\n';
if(l<=now.s
&&now.t<=r
&&now.sec<v){//不能取等,否则无法更新次大值
int dlt=now.mxa-v;
now.sum-=1ll*now.cnt*dlt;
now.mxa=v,now.lz1-=dlt;
return;
}
pushdown(p);getm;
if(l<=m)_1(_ls);
if(m<r)_1(_rs);
update(p);
return;
}
ll _3/*区间和*/(int p){
cerr<<"_3:"<<p<<'\n';
output(p);
if(l<=now.s&&now.t<=r)return now.sum;
cerr<<"lol\n";
pushdown(p);
cerr<<"pushed down\n";
ll ans=0;getm;
cerr<<"m="<<m<<'\n';
if(l<=m){
ans+=_3(_ls);
cerr<<"ls searched\n";
}
if(m<r){
ans+=_3(_rs);
cerr<<"rs searched\n";
}
cerr<<"ans="<<ans<<'\n';
update(p);
cerr<<"updated\n";
return ans;
}
int _4/*区间最大值*/(int p){
cerr<<"_4:"<<p<<'\n';
if(l<=now.s&&now.t<=r)return now.mxa;
pushdown(p);
int ans=-INT_MAX;getm;
if(l<=m)ans=max(ans,_4(_ls));
if(m<r)ans=max(ans,_4(_rs));
update(p);
return ans;
}
int _5/*区间历史最大值*/(int p){
cerr<<"_5:"<<p<<'\n';
if(l<=now.s&&now.t<=r)return now.mxb;
pushdown(p);
int ans=-INT_MAX;getm;
if(l<=m)ans=max(ans,_5(_ls));
if(m<r)ans=max(ans,_5(_rs));
update(p);
return ans;
}
int main(){
cin>>N>>M;
for(int i=1;i<=N;i++)scanf("%d",&a[i]);
build(1,N,1);
debug(1);
for(int i=1,op,r,k,v;i<=M;i++){
scanf("%d%d%d",&op,&l,&r);
cerr<<"l="<<l<<",r="<<r<<'\n';
if(op==1){
scanf("%d",&k);_1(1);
}
if(op==2){
scanf("%d",&v);_2(1);
}
if(op==3)printf("%lld\n",_3(1));
if(op==4)printf("%d\n",_4(1));
if(op==5)printf("%d\n",_5(1));
}
return 0;
}