只过了hack和样例求调,代码非常清晰且有思路、注释
查看原帖
只过了hack和样例求调,代码非常清晰且有思路、注释
22716
神仙酱楼主2024/2/26 17:10
#include <bits/stdc++.h>
#define LC tr[u << 1]
#define RC tr[u << 1 | 1]
#define PA tr[u]
#define LEN(TR) (TR.r - TR.l + 1)
using namespace std;
using ll = long long;
const int N = 1e5 + 10;
struct node_t {
    int l, r;
    int pre[2]; // pre[i]是考虑i的最大连续前缀长度
    int suc[2]; // suc[i]是考虑i的最大后缀连续长度
    int maxlen[2]; // maxlen[i]是连续的i的最大的长度 
    int sum, tag = -1; // tag代表的是0,1,2三种操作。-1代表无操作。
} tr[4 * N];
int a[N];

void pushup(int u) {
    // 分别维护各个属性
    PA.sum = LC.sum + RC.sum;
    for (int i = 0; i < 2; ++i) {
        PA.maxlen[i] = max(max(LC.maxlen[i], RC.maxlen[i]), LC.suc[i] + RC.pre[i]);
        PA.pre[i] = LC.pre[i] == LEN(LC) ? LEN(LC) + RC.pre[i] : LC.pre[i];
        PA.suc[i] = RC.suc[i] == LEN(RC) ? LEN(RC) + LC.suc[i] : RC.suc[i];
    }
}

void update(int u, int op) {
  // 根据操作op来更新当前节点的所有属性
    switch (op) {
    case 0:
        PA.maxlen[1] = PA.sum = PA.pre[1] = PA.suc[1] = 0;
        PA.maxlen[0] = PA.pre[0] = PA.suc[0] = LEN(PA);
        break;
    case 1:
        PA.maxlen[1] = PA.pre[1] = PA.suc[1] = PA.sum = LEN(PA);
        PA.maxlen[0] = PA.pre[0] = PA.suc[0] = 0;
        break;
    case 2:
        PA.sum = LEN(PA) - PA.sum;
        swap(PA.pre[0], PA.pre[1]);
        swap(PA.suc[0], PA.suc[1]);
        swap(PA.maxlen[0], PA.maxlen[1]);
    }
}

void fix_tag(int u, int op) {
  // 根据操作op来更新当前节点的tag。
    switch (op) {
    case -1:
        return;
    case 0:
    case 1:
        PA.tag = op;
        break;
    case 2:
        if (PA.tag == 0 || PA.tag == 1) // 翻转
            PA.tag = !PA.tag;
        else if (PA.tag == -1) // 覆盖
            PA.tag = op;
        else  // PA.tag == 2,覆盖
            PA.tag = -1;
    }
}

void pushdown(int u) {
    if (PA.tag == -1)
        return;
    fix_tag(u << 1, PA.tag);
    update(u << 1, LC.tag);
    fix_tag(u << 1 | 1, PA.tag);
    update(u << 1 | 1, RC.tag);
    PA.tag = -1;
}

void build(int u, int l, int r) {
    PA.l = l, PA.r = r;
    if (PA.l == PA.r) {
        PA.maxlen[1] = PA.sum = a[l] = PA.pre[1] = PA.suc[1] = a[l];
        PA.maxlen[0] = PA.pre[0] = PA.suc[0] = !a[l];
    }
    else {
        int mid = PA.l + PA.r >> 1;
        build(u << 1, l, mid);
        build(u << 1 | 1, mid + 1, r);
        pushup(u);
    }
}

void modify(int u, int l, int r, int op) {
    if (l <= PA.l && PA.r <= r) {
        update(u, op);
        fix_tag(u, op);
    }
    else {
        pushdown(u);
        int mid = PA.l + PA.r >> 1;
        if (l <= mid)
            modify(u << 1, l, r, op);
        if (mid < r)
            modify(u << 1 | 1, l, r, op);
        pushup(u);
    }
}

int query(int u, int l, int r, int op) {
    if (l <= PA.l && PA.r <= r)
        return op == 3 ? PA.sum : PA.maxlen[1];
    int mid = PA.l + PA.r >> 1;
    int ans = 0;
    pushdown(u);
    if (l <= mid)
        ans = query(u << 1, l, r, op);
    if (mid < r)
        ans += query(u << 1 | 1, l, r, op);
    return ans;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen(".in", "r", stdin);
#endif
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, m;
    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 <= 2)
            modify(1, l, r, op);
        else
            cout << query(1, l, r, op) << "\n";
    }
}
2024/2/26 17:10
加载中...