#include <bits/stdc++.h>
namespace IO{
#define LL long long
inline LL read(){
LL x=0,f=1;char c=getchar();
for (;!isdigit(c);c=getchar())if (c=='-')f=-1;
for (;isdigit(c);c=getchar())x=(x<<3)+(x<<1)+(c^48);
return x*f;
}
inline void write(LL x,char c='\n'){
if (x){
if (x<0)x=-x,putchar('-');
char a[30];short l;
for (l=0;x;x/=10)a[l++]=x%10^48;
for (l--;l>=0;l--)putchar(a[l]);
}else putchar('0');putchar(c);
}
}using namespace IO;
using namespace std;
#define int long long
inline int ls(int x){return (x<<1);}
inline int rs(int x){return (x<<1|1);}
const int N = 5e5+10;
const int INF = 9e18;
struct Segment_Tree{
int val,lzmi,lzma,lzsu;
}tree[N<<2];
int n,m,a[N];
void pushup(int now)//更新当前节点
{tree[now].val=max(tree[ls(now)].val,tree[rs(now)].val);}
void build(int now,int l,int r){
tree[now].lzmi=INF,tree[now].lzma=-INF;
if (l==r)return tree[now].val=a[l],void();
int mid=(l+r)>>1;
build(ls(now),l,mid);
build(rs(now),mid+1,r);
pushup(now);
}//建树
void pushdown(int now){
//加上当前sum懒标记
tree[ls(now)].val+=tree[now].lzsu;
tree[rs(now)].val+=tree[now].lzsu;
tree[ls(now)].lzsu+=tree[now].lzsu;
tree[rs(now)].lzsu+=tree[now].lzsu;
if (tree[ls(now)].lzmi<INF)
tree[ls(now)].lzmi+=tree[now].lzsu;
if (tree[rs(now)].lzmi<INF)
tree[rs(now)].lzmi+=tree[now].lzsu;
if (tree[ls(now)].lzma>-INF)
tree[ls(now)].lzma+=tree[now].lzsu;
if (tree[rs(now)].lzma>-INF)
tree[rs(now)].lzma+=tree[now].lzsu;
tree[now].lzsu=0;
//与当前min懒标记取最小值
tree[ls(now)].val=min(tree[ls(now)].val,tree[now].lzmi);
tree[rs(now)].val=min(tree[rs(now)].val,tree[now].lzmi);
tree[ls(now)].lzmi=min(tree[ls(now)].lzmi,tree[now].lzmi);
tree[rs(now)].lzmi=min(tree[rs(now)].lzmi,tree[now].lzmi);
tree[ls(now)].lzma=min(tree[ls(now)].lzma,tree[now].lzmi);
tree[rs(now)].lzma=min(tree[rs(now)].lzma,tree[now].lzmi);
tree[now].lzmi=INF;
//与当前max懒标记取最大值
tree[ls(now)].val=max(tree[ls(now)].val,tree[now].lzma);
tree[rs(now)].val=max(tree[rs(now)].val,tree[now].lzma);
tree[ls(now)].lzmi=max(tree[ls(now)].lzmi,tree[now].lzma);
tree[rs(now)].lzmi=max(tree[rs(now)].lzmi,tree[now].lzma);
tree[ls(now)].lzma=max(tree[ls(now)].lzma,tree[now].lzma);
tree[rs(now)].lzma=max(tree[rs(now)].lzma,tree[now].lzma);
tree[now].lzma=-INF;
}//pushdown操作
void update_sum(int now,int l,int r,int x,int y,int val){
if (x<=l&&r<=y){
tree[now].val+=val;
tree[now].lzsu+=val;
if (tree[now].lzmi<INF)tree[now].lzmi+=val;
if (tree[now].lzma>-INF)tree[now].lzma+=val;
return;
}
pushdown(now);int mid=(l+r)>>1;
if (x<=mid)update_sum(ls(now),l,mid,x,y,val);
if (mid<y) update_sum(rs(now),mid+1,r,x,y,val);
pushup(now);
}//区间修改总和
void update_min(int now,int l,int r,int x,int y,int val){
if (x<=l&&r<=y){
tree[now].val=min(tree[now].val,val);
tree[now].lzmi=min(tree[now].lzmi,val);
tree[now].lzma=max(tree[now].lzma,val);
return;
}
pushdown(now);int mid=(l+r)>>1;
if (x<=mid)update_min(ls(now),l,mid,x,y,val);
if (mid<y) update_min(rs(now),mid+1,r,x,y,val);
pushup(now);
}//区间修改最小值
void update_max(int now,int l,int r,int x,int y,int val){
if (x<=l&&r<=y){
tree[now].val=max(tree[now].val,val);
tree[now].lzmi=max(tree[now].lzmi,val);
tree[now].lzma=max(tree[now].lzma,val);
return;
}
pushdown(now);int mid=(l+r)>>1;
if (x<=mid)update_max(ls(now),l,mid,x,y,val);
if (mid<y) update_max(rs(now),mid+1,r,x,y,val);
pushup(now);
}//区间修改最大值
int query(int now,int l,int r,int x,int y){
if (x<=l&&r<=y)return tree[now].val;
pushdown(now);int mid=(l+r)>>1,ans=-INF;
if (x<=mid)ans=max(ans,query(ls(now),l,mid,x,y));
if (mid<y) ans=max(ans,query(rs(now),mid+1,r,x,y));
return ans;
}//区间查询最大值
signed main(){
n=read(),m=read();
for (int i=1;i<=n;i++)a[i]=read();
build(1,1,n);
for (int i=1;i<=m;i++){
int op=read(),x=read(),y=read(),val;
if (op==1)val=read(),update_sum(1,1,n,x,y,val);
if (op==2)val=read(),update_min(1,1,n,x,y,val);
if (op==3)val=read(),update_max(1,1,n,x,y,val);
if (op==4)write(query(1,1,n,x,y));
}
return 0;
}
#1 AC,其余 WA+TLE。