(#10数据文件过大无法下载。。)
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 3;
const ll inf = 1e18 + 3;
int n, m;
ll a[MAXN];
struct node {
int l, r;
ll w;
ll add, set;
} tree[MAXN * 4];
void pushup(int u) {
tree[u].w = max(tree[u * 2].w, tree[u * 2 + 1].w);
}
void build(int u, int l, int r) {
tree[u].l = l;
tree[u].r = r;
tree[u].set = inf;
if (l == r) {
tree[u].w = a[l];
return;
}
int mid = l + r >> 1;
build(u * 2, l, mid); build(u * 2 + 1, mid + 1, r);
pushup(u);
}
inline bool inRange(int l, int r, int L, int R) {
return l >= L && r <= R;
}
inline bool outOfRange(int l, int r, int L, int R) {
return r < L || l > R;
}
void makeAddTag(int u, ll x) {
if (tree[u].set == inf)
tree[u].add += x;
else
tree[u].set += x;
tree[u].w += x;
}
void makeSetTag(int u, ll x) {
tree[u].add = 0;
tree[u].set = x;
tree[u].w = x;
}
void pushdown(int u) {
if (tree[u].set == inf) {
makeAddTag(u * 2, tree[u].add);
makeAddTag(u * 2 + 1, tree[u].add);
tree[u].add = 0;
}
else {
makeSetTag(u * 2, tree[u].set);
makeSetTag(u * 2 + 1, tree[u].set);
tree[u].set = inf;
}
}
ll query(int u, int L, int R) {
if (inRange(tree[u].l, tree[u].r, L, R))
return tree[u].w;
if (!outOfRange(tree[u].l, tree[u].r, L, R)) {
pushdown(u);
return max(query(u * 2, L, R), query(u * 2 + 1, L, R));
}
return -inf;
}
void add(int u, int L, int R, ll x) {
if (inRange(tree[u].l, tree[u].r, L, R))
makeAddTag(u, x);
else if (!outOfRange(tree[u].l, tree[u].r, L, R)) {
pushdown(u);
add(u * 2, L, R, x);
add(u * 2 + 1, L, R, x);
pushup(u);
}
}
void set(int u, int L, int R, ll x) {
if (inRange(tree[u].l, tree[u].r, L, R))
makeSetTag(u, x);
else if (!outOfRange(tree[u].l, tree[u].r, L, R)) {
pushdown(u);
set(u * 2, L, R, x);
set(u * 2 + 1, L, R, x);
pushup(u);
}
}
int main() {
cin.tie(nullptr) -> sync_with_stdio(false);
cin >> n >> m;
for (int i=1; i<=n; i++)
cin >> a[i];
build(1, 1, MAXN);
for (int i=0; i<m; i++) {
int op, x, y;
cin >> op;
switch (op) {
case 1:
ll k1;
cin >> x >> y >> k1;
set(1, x, y, k1);
break;
case 2:
ll k2;
cin >> x >> y >> k2;
add(1, x, y, k2);
break;
case 3:
cin >> x >> y;
cout << query(1, x, y) << "\n";
}
}
return 0;
}