- 给一个区间[L,R] 加上一个数x
- 把一个区间[L,R] 里小于x 的数变成x
- 把一个区间[L,R] 里大于x 的数变成x
- 求区间[L,R] 的和
- 求区间[L,R] 的最大值
- 求区间[L,R] 的最小值
由吉老师线段树基础进阶。增加了区间加操作
但对于同时进行23操作的话,也多了一个特判,就是最大值修改时要判断最小值和次小值,也得进行修改
其次,对于区间加操作,就是多加了一个lazy标记,用与区间加的向下传递操作,而且lazy的优先级是大于其他两个修改操作的
其他方法就和之前的一样,维护一个最大值,次大值,最大值个数,最小值,次小值,最小值个数,每次修改都进行3种情况的分类讨论即可
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 5e5, INF = 1 << 30;
int a[N];
struct Segment_Tree{
struct Node{
int l, r;
int mx, mxse, mxcnt; // 维护最大值
int mi, mise, micnt; // 维护最小值
ll sum, lazy; // 区间和
#define l(p) tree[p].l
#define r(p) tree[p].r
#define mx(p) tree[p].mx
#define mi(p) tree[p].mi
#define mxse(p) tree[p].mxse
#define mise(p) tree[p].mise
#define mxcnt(p) tree[p].mxcnt
#define micnt(p) tree[p].micnt
#define sum(p) tree[p].sum
#define lazy(p) tree[p].lazy
#define lson (p << 1)
#define rson (p << 1 | 1)
} tree[N << 2];
void pushup(int p) {
sum(p) = sum(lson) + sum(rson);
mx(p) = max(mx(lson), mx(rson));
mi(p) = min(mi(lson), mi(rson));
mxcnt(p) = micnt(p) = 0;
if(mx(lson) == mx(rson)) {
mxcnt(p) = mxcnt(lson) + mxcnt(rson);
mxse(p) = max(mxse(lson), mxse(rson));
}else {
if(mx(lson) > mx(rson)) {
mxcnt(p) = mxcnt(lson);
mxse(p) = max(mxse(lson), mx(rson));
}else {
mxcnt(p) = mxcnt(rson);
mxse(p) = max(mxse(rson), mx(lson));
}
}
if(mi(lson) == mi(rson)) {
micnt(p) = micnt(lson) + micnt(rson);
mise(p) = min(mise(lson), mise(rson));
}else {
if(mi(lson) < mi(rson)) {
micnt(p) = micnt(lson);
mise(p) = min(mise(lson), mi(rson));
}else {
micnt(p) = micnt(rson);
mise(p) = min(mise(rson), mi(lson));
}
}
}
void pushdown(int p) {
if(lazy(p)) {
mx(lson) += lazy(p); mx(rson) += lazy(p); mxse(lson) += lazy(p); mxse(rson) += lazy(p);
mi(lson) += lazy(p); mi(rson) += lazy(p); mise(lson) += lazy(p); mise(rson) += lazy(p);
lazy(lson) += lazy(p); lazy(rson) += lazy(p);
sum(lson) += 1ll * (r(lson) - l(lson) + 1) * lazy(p);
sum(rson) += 1ll * (r(rson) - l(rson) + 1) * lazy(p);
lazy(p) = 0;
}
if(mx(lson) > mx(p)) {
if(mi(lson) == mx(lson)) mi(lson) = mx(p);
if(mise(lson) == mx(lson)) mise(lson) = mx(p);
sum(lson) -= 1ll * (mx(lson) - mx(p)) * mxcnt(lson);
mx(lson) = mx(p);
}
if(mx(rson) > mx(p)) {
if(mi(rson) == mx(rson)) mi(rson) = mx(p);
if(mise(rson) == mx(rson)) mise(rson) = mx(p);
sum(rson) -= 1ll * (mx(rson) - mx(p)) * mxcnt(rson);
mx(rson) = mx(p);
}
if(mi(lson) < mi(p)) {
if(mx(lson) == mi(lson)) mx(lson) = mi(p);
if(mxse(lson) == mi(lson)) mxse(lson) = mi(p);
sum(lson) += 1ll * (mi(p) - mi(lson)) * micnt(lson);
mi(lson) = mi(p);
}
if(mi(rson) < mi(p)) {
if(mx(rson) == mi(rson)) mx(rson) = mi(p);
if(mxse(rson) == mi(rson)) mxse(rson) = mi(p);
sum(rson) += 1ll * (mi(p) - mi(rson)) * micnt(rson);
mi(rson) = mi(p);
}
}
void build(int p, int l, int r) {
l(p) = l, r(p) = r;
lazy(p) = 0; mx(p) = mi(p) = sum(p) = 0;
mxse(p) = -INF, mise(p) = INF;
mxcnt(p) = micnt(p) = 0;
if(l == r) {
mx(p) = mi(p) = sum(p) = a[l];
mxse(p) = -INF; mise(p) = INF;
mxcnt(p) = micnt(p) = 1; lazy(p) = 0;
return;
}
int mid = (l + r) >> 1;
build(lson, l, mid); build(rson, mid + 1, r);
pushup(p);
}
void Change_max(int p, int l, int r, ll x) { // [l, r] a[i] = max(x, a[i])
if(mi(p) >= x) return;
if(l <= l(p) && r(p) <= r && mise(p) > x) {
if(mx(p) == mi(p)) mx(p) = x;
if(mxse(p) == mi(p)) mxse(p) = x;
sum(p) += 1ll * (x - mi(p)) * micnt(p); mi(p) = x;
return;
}
pushdown(p);
int mid = (l(p) + r(p)) >> 1;
if(l <= mid) Change_max(lson, l, r, x);
if(r > mid) Change_max(rson, l, r, x);
pushup(p);
}
void Change_min(int p, int l, int r, ll x) { // [l,r] a[i] = min(x, a[i])
if(mx(p) <= x) return;
if(l <= l(p) && r(p) <= r && mxse(p) < x) {
if(mi(p) == mx(p)) mi(p) = x;
if(mise(p) == mx(p)) mise(p) = x;
sum(p) -= 1ll * (mx(p) - x) * mxcnt(p); mx(p) = x;
return;
}
pushdown(p);
int mid = (l(p) + r(p)) >> 1;
if(l <= mid) Change_min(lson, l, r, x);
if(r > mid) Change_min(rson, l, r, x);
pushup(p);
}
void Change_add(int p, int l, int r, ll x) {
if(l <= l(p) && r(p) <= r) {
mx(p) += x; mi(p) += x;
mise(p) += x; mxse(p) += x;
sum(p) += 1ll * (r(p) - l(p) + 1) * x;
lazy(p) += x;
return;
}
pushdown(p);
int mid = (l(p) + r(p)) >> 1;
if(l <= mid) Change_add(lson, l, r, x);
if(r > mid) Change_add(rson, l, r, x);
pushup(p);
}
int Query_min(int p, int l, int r) {
if(l <= l(p) && r(p) <= r) return mi(p);
pushdown(p);
int mid = (l(p) + r(p)) >> 1;
int ans = INF;
if(l <= mid) ans = min(ans, Query_min(lson, l, r));
if(r > mid) ans = min(ans, Query_min(rson, l, r));
return ans;
}
int Query_max(int p, int l, int r) {
if(l <= l(p) && r(p) <= r) return mx(p);
pushdown(p);
int mid = (l(p) + r(p)) >> 1;
int ans = -INF;
if(l <= mid) ans = max(ans, Query_max(lson, l, r));
if(r > mid) ans = max(ans, Query_max(rson, l, r));
return ans;
}
ll Query_sum(int p, int l, int r) {
if(l <= l(p) && r(p) <= r) return sum(p);
pushdown(p);
int mid = (l(p) + r(p)) >> 1;
ll ans = 0;
if(l <= mid) ans += Query_sum(lson, l, r);
if(r > mid) ans += Query_sum(rson, l, r);
return ans;
}
} seg;
int main(){
int n; scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
int m; scanf("%d", &m);
seg.build(1, 1, n);
for(int i = 1; i <= m; i++) {
int op, l, r;
scanf("%d%d%d", &op, &l, &r);
if(op == 1) {
int x; scanf("%d", &x); seg.Change_add(1, l, r, x);
}
if(op == 2) {
int x; scanf("%d", &x); seg.Change_max(1, l, r, x);
}
if(op == 3) {
int x; scanf("%d", &x); seg.Change_min(1, l, r, x);
}
if(op == 4) printf("%lld\n", seg.Query_sum(1, l, r));
if(op == 5) printf("%d\n", seg.Query_max(1, l, r));
if(op == 6) printf("%d\n", seg.Query_min(1, l, r));
}
return 0;
}