_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;
}