code:
#include<bits/stdc++.h>
#define int long long
#define end '\n'
using namespace std;
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if(ch == '-'){
f = -1;
}
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = x * 10 + ch - 48;
ch = getchar();
}
return x * f;
}
const int N = 5e5 + 5;
int n, m;
int a[N];
struct Segment_Tree{
int mini, maxi, tag1, tag2;
}tree[N * 4];
void pushup(int node){
tree[node].maxi = max(tree[node << 1].maxi, tree[node << 1 | 1].maxi);
tree[node].mini = min(tree[node << 1].mini, tree[node << 1 | 1].mini);
}
void addtag1(int node, int val){
tree[node].maxi += val;
tree[node].mini += val;
tree[node].tag1 += val;
}
void addtag2(int node, int val){
tree[node].maxi = val;
tree[node].mini = val;
tree[node].tag2 = val;
tree[node].tag1 = 0;
}
void pushdown(int node, int lt, int rt){
if(tree[node].tag2 != 0){
addtag2(node << 1, tree[node].tag2);
addtag2(node << 1 | 1, tree[node].tag2);
tree[node].tag2 = 0;
}
if(tree[node].tag1 != 0){
addtag1(node << 1, tree[node].tag1);
addtag1(node << 1 | 1, tree[node].tag1);
tree[node].tag1 = 0;
}
}
void build(int node, int lt, int rt){
if(lt == rt){
tree[node].maxi = tree[node].mini = a[lt];
return ;
}
int mid = lt + rt >> 1;
build(node << 1, lt, mid);
build(node << 1 | 1, mid + 1, rt);
pushup(node);
}
void update(int node, int lt, int rt, int x, int y, int val){
if(x > rt || y < lt){
return ;
}
if(x <= lt && rt <= y){
addtag1(node, val);
return ;
}
pushdown(node, lt, rt);
int mid = lt + rt >> 1;
update(node << 1, lt, mid, x, y, val);
update(node << 1 | 1, mid + 1, rt, x, y, val);
pushup(node);
}
void update_min(int node, int lt, int rt, int x, int y, int val){
if(x > rt || y < lt){
return ;
}
if(x <= lt && rt <= y){
if(tree[node].mini >= val){
tree[node].mini = tree[node].maxi = tree[node].tag2 = val;
tree[node].tag1 = 0;
}
if(tree[node].maxi <= val){
return ;
}
pushdown(node, lt, rt);
int mid = lt + rt >> 1;
update_min(node << 1, lt, mid, x, y, val);
update_min(node << 1 | 1, mid + 1, rt, x, y, val);
pushup(node);
return ;
}
pushdown(node, lt, rt);
int mid = lt + rt >> 1;
update_min(node << 1, lt, mid, x, y, val);
update_min(node << 1 | 1, mid + 1, rt, x, y, val);
pushup(node);
}
void update_max(int node, int lt, int rt, int x, int y, int val){
if(x > rt || y < lt){
return ;
}
if(x <= lt && rt <= y){
if(tree[node].maxi <= val){
tree[node].mini = tree[node].maxi = tree[node].tag2 = val;
tree[node].tag1 = 0;
}
if(tree[node].mini >= val){
return ;
}
pushdown(node, lt, rt);
int mid = lt + rt >> 1;
update_min(node << 1, lt, mid, x, y, val);
update_min(node << 1 | 1, mid + 1, rt, x, y, val);
pushup(node);
return ;
}
pushdown(node, lt, rt);
int mid = lt + rt >> 1;
update_min(node << 1, lt, mid, x, y, val);
update_min(node << 1 | 1, mid + 1, rt, x, y, val);
pushup(node);
}
int query(int node, int lt, int rt, int x, int y){
if(x > rt || y < lt){
return -1e9;
}
if(x <= lt && rt <= y){
return tree[node].maxi;
}
pushdown(node, lt, rt);
int mid = lt + rt >> 1;
return max(query(node << 1, lt, mid, x, y), query(node << 1 | 1, mid + 1, rt, x, y));
}
void Solve(){
cin >> n >> m;
for(int i = 1; i <= n; i++){
a[i] = read();
}
build(1, 1, n);
while(m--){
int op;
cin >> op;
if(op == 1){
int x, y, k;
x = read(), y = read(), k = read();
update(1, 1, n, x, y, k);
}
if(op == 2){
int x, y, k;
x = read(), y = read(), k = read();
update_min(1, 1, n, x, y, k);
}
if(op == 3){
int x, y, k;
x = read(), y = read(), k = read();
update_max(1, 1, n, x, y, k);
}
if(op == 4){
int x, y;
x = read(), y = read();
printf("%lld\n", query(1, 1, n, x, y));
}
}
}
signed main(){
Solve();
return 0;
}