#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1000005, INF = 1e17;
int n, q;
int a[N], tree[N * 4], add[N * 4], eqa[N * 4];
struct Segment_Tree{
void pushdown(int k){
if (eqa[k] != INF){
tree[k << 1] = eqa[k << 1] = eqa[k];
add[k << 1] = 0;
tree[k << 1 | 1] = eqa[k << 1 | 1] = eqa[k];
add[k << 1 | 1] = 0;
eqa[k] = INF;
}
add[k << 1] += add[k];
tree[k << 1] += add[k];
add[k << 1 | 1] += add[k];
tree[k << 1 | 1] += add[k];
add[k] = 0;
}
void pushup(int k){
tree[k] = max(tree[k << 1], tree[k << 1 | 1]);
}
void build(int k, int l, int r){
eqa[k] = INF;
if (l == r){
tree[k] = a[l];
return ;
}
int mid = (l + r) >> 1;
build(k << 1, l, mid);
build(k << 1 | 1, mid + 1, r);
pushup(k);
}
void ud1(int k, int l, int r, int x, int y, int v){
if (l >= x && r <= y){
tree[k] = v;
eqa[k] = v;
return ;
}
pushdown(k);
int mid = (l + r) >> 1;
if (x <= mid) ud1(k << 1, l, mid, x, y, v);
if (y >= mid + 1) ud1(k << 1 | 1, mid + 1, r, x, y, v);
pushup(k);
}
void ud2(int k, int l, int r, int x, int y, int v){
if (l >= x && r <= y){
tree[k] += v;
add[k] += v;
return ;
}
pushdown(k);
int mid = (l + r) >> 1;
if (x <= mid) ud2(k << 1, l, mid, x, y, v);
if (y >= mid + 1) ud2(k << 1 | 1, mid + 1, r, x, y, v);
pushup(k);
}
int ask(int k, int l, int r, int x, int y){
if (l >= x && r <= y) return tree[k];
pushdown(k);
int mid = (l + r) >> 1, res = -INF;
if (x <= mid) res = max(res, ask(k << 1, l, mid, x, y));
if (y >= mid + 1) res = max(res, ask(k << 1 | 1, mid + 1, r, x, y));
return res;
}
}SGT;
signed main(){
scanf("%lld %lld", &n, &q);
for (int i = 1; i <= n; i++){
scanf("%lld", &a[i]);
}
SGT.build(1, 1, n);
while(q--){
int opt, l, r, x;
scanf("%lld %lld %lld", &opt, &l, &r);
if (opt == 1){
scanf("%lld", &x);
SGT.ud1(1, 1, n, l, r, x);
}
if (opt == 2){
scanf("%lld", &x);
SGT.ud2(1, 1, n, l, r, x);
}
if (opt == 3){
printf("%lld\n", SGT.ask(1, 1, n, l, r));
}
}
return 0;
}