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

2 years ago
// 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;
}