黑暗爆炸 - 4695 最假女选手 - 吉老师线段树

传送门

  1. 给一个区间[L,R] 加上一个数x
  2. 把一个区间[L,R] 里小于x 的数变成x
  3. 把一个区间[L,R] 里大于x 的数变成x
  4. 求区间[L,R] 的和
  5. 求区间[L,R] 的最大值
  6. 求区间[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;
}
上一篇:arc 043 c 题解


下一篇:CF343D Water Tree