#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<set>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#include<iostream>
#include<string>
#include<cmath>
#define FOR(i,a,b) for(i=(a);i<=(b);i++)
#define ROF(i,a,b) for(i=(a);i>=(b);i--)
#define N 100010
typedef long long LL;
using namespace std;
int swap(int &x,int &y){int t=x;x=y;y=t;}
int L=0,ans[N],a[N];
struct Splay
{
int lc[3*N],rc[3*N],tp[3*N],s[3*N],fa[3*N],key[3*N],ct[3*N],rev[3*N],lazy[3*N],Max[3*N];
int root,len,cnt,inf,sta[N],top;
void init(){root=len=cnt=0;inf=2e9;}
void upd(int x)
{
if (x==0) return;
Max[x]=key[x];
if (lc[x]>0) Max[x]=max(Max[x],Max[lc[x]]);
if (rc[x]>0) Max[x]=max(Max[x],Max[rc[x]]);
}
void lt(int x)
{
int y=fa[x];tp[x]=tp[y];fa[x]=fa[y];tp[y]=1;fa[y]=x;
s[x]=s[y];s[y]=s[rc[y]]+s[rc[x]]+ct[y];
if (rc[x]!=0) {fa[rc[x]]=y;tp[rc[x]]=0;}
lc[y]=rc[x];rc[x]=y;
if (fa[x]==0) root=x;
upd(y);upd(x);
}
void rt(int x)
{
int y=fa[x];tp[x]=tp[y];fa[x]=fa[y];tp[y]=0;fa[y]=x;
s[x]=s[y];s[y]=s[lc[y]]+s[lc[x]]+ct[y];
if (lc[x]!=0) {fa[lc[x]]=y;tp[lc[x]]=1;}
rc[y]=lc[x];lc[x]=y;
if (fa[x]==0) root=x;
upd(y);upd(x);
}
void rotate(int x)
{
pushdown(fa[x]);
pushdown(x);
if (tp[x]==0) lt(x);else rt(x);
}
void pushdown(int x)
{
if (rev[x]==1)
{
swap(lc[x],rc[x]);
tp[lc[x]]=0;tp[rc[x]]=1;
rev[lc[x]]^=1;rev[rc[x]]^=1;
rev[x]=0;
}
key[lc[x]]+=lazy[x];key[rc[x]]+=lazy[x];
Max[lc[x]]+=lazy[x];Max[rc[x]]+=lazy[x];
lazy[lc[x]]+=lazy[x];lazy[rc[x]]+=lazy[x];
lazy[x]=0;
}
void splay(int x)
{
int t=x;
while (t!=root) rotate(t);
}
void build(int x,int L,int R)
{
int mid=(L+R)>>1;
key[x]=a[mid];s[x]=ct[x]=1;rev[x]=0;Max[x]=key[x];
if (mid>L)
{
lc[x]=++len;fa[lc[x]]=x;tp[lc[x]]=0;
build(lc[x],L,mid-1);s[x]+=s[lc[x]];
}
if (mid<R)
{
rc[x]=++len;fa[rc[x]]=x;tp[rc[x]]=1;
build(rc[x],mid+1,R);s[x]+=s[rc[x]];
}
upd(x);
}
int select(int x,int ks)
{
pushdown(x);
int ls=s[lc[x]];
if (ks<=ls) return select(lc[x],ks);
if (ks<=ls+ct[x]) return x;
return select(rc[x],ks-ls-ct[x]);
}
int getid(int L,int R)
{
int pL=select(root,L-1+1);
splay(pL);
int troot=root;
int pR=select(root,R+1+1);
root=rc[root];
fa[root]=0;
splay(pR);
fa[root]=troot;tp[root]=1;rc[troot]=root;
root=troot;upd(lc[root]);upd(root);
return lc[rc[root]];
}
void reverse(int L,int R)
{
if (L>R) return;
int id=getid(L,R);
rev[id]^=1; }
void change(int L,int R,int d)
{
if (L>R) return;
int id=getid(L,R);
lazy[id]+=d;key[id]+=d;Max[id]+=d; upd(fa[id]);upd(fa[fa[id]]);
}
int getmax(int L,int R)
{
int id=getid(L,R);
return Max[id];
}
}tree;
int main()
{
tree.init();
tree.root=1;tree.len=1;
int i,n,m;
scanf("%d%d",&n,&m);
memset(a,0,sizeof(a));
a[0]=a[n+1]=-1e9;
tree.build(tree.root,0,n+1);
FOR(i,1,m)
{
int op,t1,t2,t3;
scanf("%d %d %d",&op,&t1,&t2);
if (op==1)
{
scanf("%d",&t3);
tree.change(t1,t2,t3);
}else if (op==2)
{
tree.reverse(t1,t2);
}else
{
int ans=tree.getmax(t1,t2);
printf("%d\n",ans);
}
}
}