求调,全RE

P2572 [SCOI2010] 序列操作

_zth @ 2025-01-11 21:09:27

#include <bits/stdc++.h>
#define ls u<<1
#define rs u<<1|1
#define len(u) tr[u].len
#define sum1(u) tr[u].sum1
#define maxn1(u) tr[u].maxn1
#define maxn0(u) tr[u].maxn0
#define ml1(u) tr[u].ml1
#define mr1(u) tr[u].mr1
#define ml0(u) tr[u].ml0
#define mr0(u) tr[u].mr0
#define tag1(u) tr[u].tag1
#define tag2(u) tr[u].tag2
using namespace std;

const int N = 1e5 + 10;
int n, m, a[N];

struct Tree{
    int l, r, len;
    int sum1; // 1的总数
    int maxn1, maxn0; // 1的最大个数, 0的最大个数
    int ml1, mr1, ml0, mr0; // 左右连续1、0的最大个数
    int tag1, tag2; // 区间翻转, 区间覆盖
}tr[N * 4];

void pushup(int u){
    sum1(u) = sum1(ls) + sum1(rs);
    if (maxn1(ls) == len(ls)) ml1(u) = len(ls) + ml1(rs); else ml1(u) = ml1(ls);
    if (maxn1(rs) == len(rs)) mr1(u) = len(rs) + mr1(ls); else mr1(u) = mr1(rs);
    maxn1(u) = max(max(maxn1(ls), maxn1(rs)), mr1(ls) + ml1(rs));
    // 0
    if (maxn0(ls) == len(ls)) ml0(u) = len(ls) + ml0(rs); else ml0(u) = ml0(ls);
    if (maxn0(rs) == len(rs)) mr0(u) = len(rs) + mr0(ls); else mr0(u) = mr0(rs);
    maxn0(u) = max(max(maxn0(ls), maxn0(rs)), mr0(ls) + ml0(rs));
}

void pushdown(int u){
    if (tag1(u) == 1){ // all are 0
        // left son
        maxn0(ls) = ml0(ls) = mr0(ls) = len(ls);
        sum1(ls) = maxn1(ls) = ml1(ls) = mr1(ls) = 0;
        tag1(ls) = 1, tag2(ls) = 0;
        //right son
        maxn0(rs) = ml0(rs) = mr0(rs) = len(rs);
        sum1(rs) = maxn1(rs) = ml1(rs) = mr1(rs) = 0;
        tag1(rs) = 1, tag2(rs) = 0;
        //root
        tag1(u) = 0; tag2(u) = 0;
    }
    if (tag1(u) == 2){ // all are 1
        // left son
        maxn0(ls) = ml0(ls) = mr0(ls) = 0;
        sum1(ls) = maxn1(ls) = ml1(ls) = mr1(ls) = len(ls);
        tag1(ls) = 2, tag2(ls) = 0;
        // right son
        maxn0(rs) = ml0(rs) = mr0(rs) = 0;
        sum1(rs) = maxn1(rs) = ml1(rs) = mr1(rs) = len(rs);
        tag1(rs) = 2, tag2(rs) = 0;
        // root
        tag1(u) = 0; tag2(u) = 0;
    }
    if (tag2(u)){
        sum1(ls) = len(ls) - sum1(ls);
        swap(maxn0(ls), maxn1(ls));
        swap(ml1(ls), ml0(ls));
        swap(mr1(ls), mr0(ls));
        if (tag1(ls) == 1) tag1(ls) = 2;
        else if (tag1(ls) == 2) tag1(ls) = 1;
        else tag2(ls) ^= 1;

        sum1(rs) = len(rs) - sum1(rs);
        swap(maxn0(rs), maxn1(rs));
        swap(ml1(rs), ml0(rs));
        swap(mr1(rs), mr0(rs));
        if (tag1(rs) == 1) tag1(rs) = 2;
        else if (tag1(rs) == 2) tag1(rs) = 1;
        else tag2(rs) ^= 1;

        tag2(u) = 0;
    }
}

void build(int u, int l, int r){
    tr[u].l = l, tr[u].r = r, tr[u].len = r - l + 1;
    if (l == r){
        sum1(u) = a[l];
        ml1(u) = mr1(u) = maxn1(u) = ((a[l]==1)?1:0);
        ml0(u) = mr0(u) = maxn0(u) = ((a[l]==1)?1:0);
        return ;
    }
    int mid = l + r >> 1;
    build(u << 1, l, mid); build(u << 1 | 1, mid + 1, r);
    pushup(u);
}

void change(int u, int l, int r, int d){
    pushdown(u);
    if (tr[u].l == l && tr[u].r == r){
        if (d == 1){
            maxn0(u) = ml0(u) = mr0(u) = len(u);
            sum1(u) = maxn1(u) = ml1(u) = mr1(u) = 0;
            tag1(u) = 1; tag2(u) = 0;
        }
        else if (d == 2){
            maxn0(u) = ml0(u) = mr0(u) = 0;
            sum1(u) = maxn1(u) = ml1(u) = mr1(u) = len(u);
            tag1(u) = 2; tag2(u) = 0;
        }
        else {
            sum1(u) = len(u) - sum1(u);
            swap(maxn0(u), maxn1(u));
            swap(ml1(u), ml0(u));
            swap(mr1(u), mr0(u));
            tag2(u) ^= 1;
        }
        return ;
    }
    int mid = l + r >> 1;
    if (r <= mid) change(u << 1, l, r, d);
    else if (l > mid) change(u << 1 | 1, l, r, d);
    else change(u << 1, l, mid, d), change(u << 1 | 1, mid + 1, r, d);
    pushup(u);
}

int query1(int u, int l, int r){
    pushdown(u);
    if (tr[u].l == l && tr[u].r == r) return sum1(u);
    int mid = l + r >> 1;
    if (r <= mid) return query1(u << 1, l, r);
    else if (l > mid) return query1(u << 1 | 1, l, r);
    else return query1(u << 1, l, mid) + query1(u << 1 | 1, mid + 1, r);
}

int query2(int u, int l, int r){
    pushdown(u);
    if (tr[u].l == l && tr[u].r == r) return maxn1(u);
    int mid = l + r >> 1;
    if (r <= mid) return query2(u << 1, l, r);
    else if (l > mid) return query2(u << 1 | 1, l, r);
    else return max(max(query2(u << 1, l, mid), query2(u << 1 | 1, mid + 1, r)), min(ml1(rs), r - mid) + min(mr1(ls), mid - l + 1));
}

int main() 
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++) cin >> a[i];

    build(1, 1, n);

    while (m--){
        int op, l, r; cin >> op >> l >> r;
        l++, r++;
        if (op == 0) change(1, l, r, 1);
        else if (op == 1) change(1, l, r, 2);
        else if (op == 2) change(1, l, r, 3);
        else if (op == 3) cout << query1(1, l, r) << endl;
        else if (op == 4) cout << query2(1, l, r) << endl;
    }

    return 0;
}

|