wanghaoyu0924 @ 2023-05-11 15:29:00
#include <bits/stdc++.h>
using namespace std;
const int MAXLENGTH = 1000005;
int N, M;
int a[MAXLENGTH] = {0}; // 记录每个元素的值
long long d[4 * MAXLENGTH] = {0}; // 记录每个结点代表区间的最大值
long long b[4 * MAXLENGTH] = {0}; // 记录加法懒标记
long long e[4 * MAXLENGTH] = {0}; // 记录赋值懒标记
bool flag[4 * MAXLENGTH] = {0}; // 是否需要赋值
void build(int s, int t, int p){
// 对 [s,t] 区间建立线段树,当前根的编号为 p
if(s==t){
d[p] = a[s];
return;
}
int m = s + ((t - s) >> 1);
build(s, m, 2 * p);
build(m+1, t, 2*p+1);
d[p] = (d[2*p] + d[2*p+1]);
}
void pushdown(int s, int t, int p){
// 表示[s, t] 区间的节点, p为该节点的编号
int m = s + ((t - s) >> 1);
if(flag[p] && s != t){
// 更新子节点的值
d[2*p] = e[p] + b[p];
d[2*p+1] = e[p] + b[p];
// 下传懒标记
e[2*p] = e[p];
e[2*p+1] = e[p];
b[2*p] = b[p];
b[2*p+1] = b[p];
flag[2*p] = 1;
flag[2*p+1] = 1;
// 重置当前节点的懒标记
flag[p] = 0;
b[p] = 0;
return;
}
if(b[p] && s != t){
// 更新子节点的值
d[2*p] += b[p];
d[2*p+1] += b[p];
// 下传懒标记
b[2*p] += b[p];
b[2*p+1] += b[p];
// 重置当前节点的懒标记
b[p] = 0;
}
}
void pushup(int p){
// 表示[s, t] 区间的节点, p为该节点的编号
d[p] = max(d[2*p], d[2*p+1]);
}
void update_add(int l, int r, int c, int s, int t, int p){
// [l, r] 为修改区间, c 为被修改的元素的变化量,
// [s, t] 为当前节点包含的区间, p 为当前节点的编号
if(l <= s && r >= t){ // [s, t]是[l, r]的子区间
d[p] += c;
b[p] += c;
return;
}
pushdown(s, t, p);
int m = s + ((t - s) >> 1);
if(l <= m) // 需要更新左子节点
update_add(l, r, c, s, m, 2*p);
if(r > m) // 需要更新右子节点
update_add(l, r, c, m+1, t, 2*p+1);
pushup(p);
}
void update_rename(int l, int r, int c, int s, int t, int p){
// [l, r] 为修改区间, c 为被修改的元素的变化量,
// [s, t] 为当前节点包含的区间, p 为当前节点的编号
if(l <= s && r >= t){ // [s, t]是[l, r]的子区间
d[p] = c;
b[p] = 0;
e[p] = c;
flag[p] = 1;
return;
}
pushdown(s, t, p);
int m = s + ((t - s) >> 1);
if(l <= m) // 需要更新左子节点
update_rename(l, r, c, s, m, 2*p);
if(r > m) // 需要更新右子节点
update_rename(l, r, c, m+1, t, 2*p+1);
pushup(p);
}
long long solve(int l, int r, int s, int t, int p){
// [l, r] 为查询区间, [s, t] 为当前节点包含的区间, p 为当前节点的编号
if(l <= s && r >= t) // [s, t]是[l, r]的子区间
return d[p];
int m = s + ((t - s) >> 1);
pushdown(s, t, p);
long long maxi = 1<<31;
if(l <= m) maxi = max(maxi, solve(l, r, s, m, 2*p));
if(r > m) maxi = max(maxi, solve(l, r, m+1, t, 2*p+1));
return maxi;
}
int main(){
cin>>N>>M;
for(int i = 1; i <= N; i++){
cin>>a[i];
}
build(1, N, 1);
int op;
int x, y, k;
for(int i = 1; i <= M; i++){
cin>>op>>x>>y;
if(op == 1){
// 将区间[x, y]内每个数赋为k
cin>>k;
update_rename(x, y, k, 1, N, 1);
}
else if(op == 2){
// 将区间[x, y]内每个数加上k
cin>>k;
update_add(x, y, k, 1, N, 1);
}
else if(op==3){
// 输出区间[x, y]内的最大值
cout<<solve(x, y, 1, N, 1)<<endl;
}
}
return 0;
}