#include using namespace std; const int N = 200010; // 线段树,求区间连续序列长度 #define mid ((l + r) >> 1) #define ls (u << 1) #define rs (u << 1 | 1) struct Node { int l, r, len; int sum; // 区间中数字1个数 int mx[2], lx[2], rx[2]; // 区间内连续最长数字1,左起最长数字1长度,右起最长数字1长度 int turn, assign; // 取反懒标记,赋值懒标记 } tr[N << 2]; void pushup(int u) { // 更新需要更新的属性,本题是1+2+2+2=7个需要更新的属性 tr[u].sum = tr[ls].sum + tr[rs].sum; // 区间中1的个数为左右子树中1的个数和 for (int i = 0; i <= 1; i++) { tr[u].lx[i] = tr[ls].lx[i]; // 继承左儿子的左端点最多连续0/1个数 if (tr[ls].sum == i * tr[ls].len) tr[u].lx[i] += tr[rs].lx[i]; // 如果左儿子全是0/1,那么加上右儿子的左端点最长连续0/1个数 tr[u].rx[i] = tr[rs].rx[i]; if (tr[rs].sum == i * tr[rs].len) tr[u].rx[i] += tr[ls].rx[i]; tr[u].mx[i] = max({tr[ls].mx[i], tr[rs].mx[i], tr[ls].rx[i] + tr[rs].lx[i]}); } } void build(int u, int l, int r) { tr[u].l = l, tr[u].r = r, tr[u].len = r - l + 1; tr[u].assign = -1; if (l == r) { int v; cin >> v; tr[u].sum = v; tr[u].mx[v] = tr[u].lx[v] = tr[u].rx[v] = 1; return; } build(ls, l, mid), build(rs, mid + 1, r); pushup(u); } void change_turn(int u) { // 处理统计信息 tr[u].sum = tr[u].len - tr[u].sum; swap(tr[u].mx[1], tr[u].mx[0]); swap(tr[u].lx[1], tr[u].lx[0]); swap(tr[u].rx[1], tr[u].rx[0]); // 处理懒标记 if (tr[u].assign != -1) tr[u].assign ^= 1; else tr[u].turn ^= 1; } void change_all(int u, int v) { // 处理统计信息 tr[u].mx[1] = tr[u].lx[1] = tr[u].rx[1] = tr[u].sum = v * tr[u].len; tr[u].mx[0] = tr[u].lx[0] = tr[u].rx[0] = tr[u].len - tr[u].sum; // 处理懒标记 tr[u].assign = v; tr[u].turn = 0; } /* 懒标记传递流程 (1) modify ① 如果整体命中,调用change()函数处理当前区间 ② 如果未整体命中,pushdown(),然后分裂 (2) change()函数:根据懒标记 ① 修改当前区间统计信息 ② 整理当前区间懒标记,以便向下推送 (3) pushdown 如果存在某个懒标记,调用change()处理左右儿子区间,清空懒标记 */ void pushdown(int u) { // 下传懒标记 // 多个懒标记的处理原则:谁的优先级高就先处理谁,很明显,本题中的赋值运算优先级高 if (tr[u].assign != -1) { // 如果存在赋值懒标记 change_all(ls, tr[u].assign); // 向左儿子传递懒标记 change_all(rs, tr[u].assign); // 向右儿子传递懒标记 tr[u].assign = -1; // 清空赋值懒标记 } if (tr[u].turn) { // 如果存在取反的懒标记 change_turn(ls); // 向左儿子传递懒标记 change_turn(rs); // 向右儿子传递懒标记 tr[u].turn = 0; // 清空取反懒标记 } } void modify_turn(int u, int L, int R) { int l = tr[u].l, r = tr[u].r; if (l >= L && r <= R) { change_turn(u); return; } if (l > R || r < L) return; pushdown(u); modify_turn(ls, L, R), modify_turn(rs, L, R); pushup(u); } void modify_assign(int u, int L, int R, int v) { int l = tr[u].l, r = tr[u].r; if (l >= L && r <= R) { change_all(u, v); return; } if (l > R || r < L) return; pushdown(u); modify_assign(ls, L, R, v), modify_assign(rs, L, R, v); pushup(u); } int query_all(int u, int L, int R) { int l = tr[u].l, r = tr[u].r; if (l >= L && r <= R) return tr[u].sum; if (l > R || r < L) return 0; pushdown(u); return query_all(ls, L, R) + query_all(rs, L, R); } int query_continue(int u, int L, int R) { int l = tr[u].l, r = tr[u].r; if (L <= l && r <= R) return tr[u].mx[1]; if (r < L || l > R) return 0; pushdown(u); return max({query_continue(ls, L, R), query_continue(rs, L, R), min(mid - L + 1, tr[ls].rx[1]) + min(R - mid, tr[rs].lx[1])}); } int main() { #ifndef ONLINE_JUDGE freopen("P2572.in", "r", stdin); #endif // 加快读入 ios::sync_with_stdio(false), cin.tie(0); int n, m; cin >> n >> m; build(1, 0, n - 1); while (m--) { int op, l, r; cin >> op >> l >> r; if (op == 0) modify_assign(1, l, r, 0); if (op == 1) modify_assign(1, l, r, 1); if (op == 2) modify_turn(1, l, r); if (op == 3) printf("%d\n", query_all(1, l, r)); // 区间内总共有多少个1 if (op == 4) printf("%d\n", query_continue(1, l, r)); // 区间内最多有多少个连续的1 } return 0; }