Files
python/TangDou/AcWing/SegmentTree/P6242.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

163 lines
4.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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