You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

163 lines
4.7 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// 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;
}