// https://www.luogu.com.cn/blog/Sqrtree/solution-p6242 /* 测试点9: 带上 inline 1.32s 去掉 inline 1.23s 结论:inline 这东西现在的时代没用了 */ #include using namespace std; typedef long long LL; const LL INF = 0x7f7f7f7f; const int N = 2000010; #define ls u << 1 #define rs u << 1 | 1 //快读 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 << 3) + (x << 1) + (ch ^ 48); ch = getchar(); } return x * f; } int n, m, op, l, r, v; struct Node { int l, r; //区间范围 LL sum; //区间和 int maxa, maxb; int cnt, se; int add1, add2, add3, add4; } t[N]; void pushup(int u) { t[u].sum = t[ls].sum + t[rs].sum; t[u].maxa = max(t[ls].maxa, t[rs].maxa); t[u].maxb = max(t[ls].maxb, t[rs].maxb); if (t[ls].maxa == t[rs].maxa) { t[u].se = max(t[ls].se, t[rs].se); t[u].cnt = t[ls].cnt + t[rs].cnt; } else if (t[ls].maxa > t[rs].maxa) { t[u].se = max(t[ls].se, t[rs].maxa); t[u].cnt = t[ls].cnt; } else { t[u].se = max(t[ls].maxa, t[rs].se); t[u].cnt = t[rs].cnt; } } void build(int u, int l, int r) { t[u].l = l, t[u].r = r; if (l == r) { t[u].sum = t[u].maxa = t[u].maxb = read(); t[u].cnt = 1, t[u].se = -INF; return; } int mid = (l + r) >> 1; build(ls, l, mid), build(rs, mid + 1, r); pushup(u); } void change(int k1, int k2, int k3, int k4, int u) { t[u].sum += 1ll * k1 * t[u].cnt + 1ll * k2 * (t[u].r - t[u].l + 1 - t[u].cnt); t[u].maxb = max(t[u].maxb, t[u].maxa + k3); t[u].maxa += k1; if (t[u].se != -INF) t[u].se += k2; t[u].add3 = max(t[u].add3, t[u].add1 + k3); t[u].add4 = max(t[u].add4, t[u].add2 + k4); t[u].add1 += k1, t[u].add2 += k2; } void pushdown(int u) { int maxn = max(t[ls].maxa, t[rs].maxa); if (t[ls].maxa == maxn) change(t[u].add1, t[u].add2, t[u].add3, t[u].add4, ls); else change(t[u].add2, t[u].add2, t[u].add4, t[u].add4, ls); if (t[rs].maxa == maxn) change(t[u].add1, t[u].add2, t[u].add3, t[u].add4, rs); else change(t[u].add2, t[u].add2, t[u].add4, t[u].add4, rs); t[u].add1 = t[u].add2 = t[u].add3 = t[u].add4 = 0; } void add(int u, int l, int r, int v) { if (l > t[u].r || r < t[u].l) return; if (l <= t[u].l && t[u].r <= r) { t[u].sum += 1ll * v * t[u].cnt + 1ll * v * (t[u].r - t[u].l + 1 - t[u].cnt); t[u].maxa += v; t[u].maxb = max(t[u].maxb, t[u].maxa); if (t[u].se != -INF) t[u].se += v; t[u].add1 += v, t[u].add2 += v; t[u].add3 = max(t[u].add3, t[u].add1); t[u].add4 = max(t[u].add4, t[u].add2); return; } pushdown(u); add(ls, l, r, v), add(rs, l, r, v); pushup(u); } void update(int u, int l, int r, int v) { if (l > t[u].r || r < t[u].l || v >= t[u].maxa) return; if (l <= t[u].l && t[u].r <= r && t[u].se < v) { int k = t[u].maxa - v; t[u].sum -= 1ll * t[u].cnt * k; t[u].maxa = v, t[u].add1 -= k; return; } pushdown(u); update(ls, l, r, v), update(rs, l, r, v); pushup(u); } LL query_sum(int u, int l, int r) { if (l > t[u].r || r < t[u].l) return 0; if (l <= t[u].l && t[u].r <= r) return t[u].sum; pushdown(u); return query_sum(ls, l, r) + query_sum(rs, l, r); } int query_maxa(int u, int l, int r) { if (l > t[u].r || r < t[u].l) return -2e9; if (l <= t[u].l && t[u].r <= r) return t[u].maxa; pushdown(u); return max(query_maxa(ls, l, r), query_maxa(rs, l, r)); } int query_maxb(int u, int l, int r) { if (l > t[u].r || r < t[u].l) return -2e9; if (l <= t[u].l && t[u].r <= r) return t[u].maxb; pushdown(u); return max(query_maxb(ls, l, r), query_maxb(rs, l, r)); } int main() { //文件输入输出 #ifndef ONLINE_JUDGE freopen("P6242.in", "r", stdin); #endif // n个叶子结点,m个操作 n = read(), m = read(); //构建线段树 build(1, 1, n); while (m--) { op = read(), l = read(), r = read(); if (op == 1) v = read(), add(1, l, r, v); //区间加 else if (op == 2) v = read(), update(1, l, r, v); //区间更新最小值 else if (op == 3) printf("%lld\n", query_sum(1, l, r)); //查询区间和 else if (op == 4) printf("%d\n", query_maxa(1, l, r)); // a[i]最大值 else printf("%d\n", query_maxb(1, l, r)); // b[i]最大值 } return 0; }