萌新刚学线段树求调

P2572 [SCOI2010] 序列操作

SillyBilly @ 2023-10-16 13:43:53

#include<bits/stdc++.h>
using namespace std;

const int maxN = 1e5 + 10;

struct Node {
    int len, l0, l1, cnt, lmax0, rmax0, lmax1, rmax1;
    Node() { len = l0 = l1 = cnt = 0; lmax0 = lmax1 = rmax0 = rmax1 = 0; }
    Node operator + (const Node& rhs) {
        if(len == 0) return rhs;
        Node res; 
        res.cnt = cnt + rhs.cnt; res.len = len + rhs.len;
        if(lmax0 == len) res.lmax0 = lmax0 + rhs.lmax0;
        else res.lmax0 = lmax0;
        if(rhs.rmax0 == rhs.len) res.rmax0 = rmax0 + rhs.rmax0;
        else res.rmax0 = rhs.rmax0;
        if(lmax1 == len) res.lmax1 = lmax1 + rhs.lmax1;
        else res.lmax1 = lmax1;
        if(rhs.rmax1 == rhs.len) res.rmax1 = rmax1 + rhs.rmax1;
        else res.rmax1 = rhs.rmax1;
        res.l0 = max(l0, rhs.l0);
        res.l0 = max(res.l0, rmax0 + rhs.lmax0);
        res.l1 = max(l1, rhs.l1);
        res.l1 = max(res.l1, rmax1 + rhs.lmax1);
        return res;
    }
    void cover(int x) {
        if(x) {
            l0 = 0, l1 = cnt = len;
            lmax0 = rmax0 = 0;
            lmax1 = rmax1 = len;
        } else {
            l0 = len, l1 = cnt = 0;
            lmax0 = rmax0 = len;
            lmax1 = rmax1 = 0;
        }
    }
    void reverse() {
        cnt = len - cnt;
        swap(l0, l1); swap(lmax0, lmax1), swap(rmax0, rmax1);
    }
    Node operator += (const Node& rhs) {
        return *this = *this + rhs;
    }
} nodes[maxN << 2];

struct SegTree {
#define ls p << 1
#define rs p << 1 | 1
#define mid ((l + r) >> 1)
    int a[maxN], tag1[maxN], tag2[maxN];
    void pushup(int p) { nodes[p] = nodes[ls] + nodes[rs]; }
    void build(int p, int l, int r) {
        tag1[p] = -1, tag2[p] = 0;
        if(l == r) {
            nodes[p].len = 1;
            return nodes[p].cover(a[l]);
        }
        build(ls, l, mid), build(rs, mid + 1, r);
        pushup(p);
    }
    void pushdown(int p) {
        if(~tag1[p]) {
            nodes[ls].cover(tag1[p]), nodes[rs].cover(tag1[p]);
            tag1[p] = -1;
        }
        if(tag2[p]) {
            nodes[ls].reverse(), nodes[rs].reverse();
            tag2[p] = 0;
        }
    }
    void cover(int p, int l, int r, int nl, int nr, int val) {
        if(nl <= l && r <= nr) {
            tag1[p] = val;
            return nodes[p].cover(val);
        }
        pushdown(p);
        if(nl <= mid) cover(ls, l, mid, nl, nr, val);
        if(nr > mid) cover(rs, mid + 1, r, nl, nr, val);
        pushup(p);
    }
    void reverse(int p, int l, int r, int nl, int nr) {
        if(nl <= l && r <= nr) {
            tag2[p] = !tag2[p];
            return nodes[p].reverse();
        }
        pushdown(p);
        if(nl <= mid) reverse(ls, l, mid, nl, nr);
        if(nr > mid) reverse(rs, mid + 1, r, nl, nr);
        pushup(p);
    }
    Node query(int p, int l, int r, int nl, int nr) {
        if(nl <= l && r <= nr) return nodes[p];
        pushdown(p);
        Node res;
        if(nl <= mid) res += query(ls, l, mid, nl, nr);
        if(nr > mid) res += query(rs, mid + 1, r, nl, nr);
        pushup(p);
        return res;
    }
} tree;

int main() {
    int n, m; cin >> n >> m;
    for(int i = 1; i <= n; i++) cin >> tree.a[i];
    tree.build(1, 1, n);
    while(m-- > 0) {
        int op, l, r; cin >> op >> l >> r; l++, r++;
        if(op == 0) tree.cover(1, 1, n, l, r, 0);
        if(op == 1) tree.cover(1, 1, n, l, r, 1);
        if(op == 2) tree.reverse(1, 1, n, l, r);
        if(op == 3) cout << tree.query(1, 1, n, l, r).cnt << "\n";
        if(op == 4) cout << tree.query(1, 1, n, l, r).l1 << "\n";
    }
}

|