|
|
// https://www.luogu.com.cn/blog/Sqrtree/solution-p6242
|
|
|
|
|
|
/* 测试点9:
|
|
|
带上 inline 1.32s
|
|
|
去掉 inline 1.23s
|
|
|
结论:inline 这东西现在的时代没用了
|
|
|
*/
|
|
|
#include <iostream>
|
|
|
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;
|
|
|
} |