题意
题解
操作 0 , 1 0,1 0,1 即简单的区间覆盖,操作 2 2 2 取反操作可以简单地交换区间内 0 , 1 0,1 0,1 的信息实现。需要维护的信息有区间 0 , 1 0,1 0,1 的总数、最大的连续长度、左连续的最大长度与右连续的最大长度。 l a z y t a g lazy\ tag lazy tag 将区间修改复杂度降至 O ( l o g N ) O(logN) O(logN),使用多个 l a z y t a g lazy\ tag lazy tag 时注意处理次序。
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 100005
#define t_size (1 << 18) - 1
struct node
{
int tot[2], cnt[2], l[2], r[2];
} tree[t_size];
int N, M, A[maxn], lzf[t_size], lzr[t_size];
node merge(node &cl, node &cr, int ln, int rn)
{
node p;
for (int i = 0; i <= 1; i++)
{
p.tot[i] = cl.tot[i] + cr.tot[i];
p.l[i] = cl.l[i] + (cl.l[i] == ln ? cr.l[i] : 0);
p.r[i] = cr.r[i] + (cr.r[i] == rn ? cl.r[i] : 0);
p.cnt[i] = max(max(cl.cnt[i], cr.cnt[i]), cl.r[i] + cr.l[i]);
}
return p;
}
inline void _swap(node &p)
{
swap(p.tot[0], p.tot[1]);
swap(p.cnt[0], p.cnt[1]);
swap(p.l[0], p.l[1]);
swap(p.r[0], p.r[1]);
}
inline void _op(int i, node &p, int l, int r)
{
int j = i ^ 1;
p.tot[i] = p.cnt[i] = p.l[i] = p.r[i] = r - l;
p.tot[j] = p.cnt[j] = p.l[j] = p.r[j] = 0;
}
inline void pushdown(int k, int chl, int chr, int l, int r, int m)
{
node &cl = tree[chl], &cr = tree[chr];
if (lzf[k] != -1)
{
_op(lzf[k], cl, l, m);
_op(lzf[k], cr, m, r);
lzf[chl] = lzf[chr] = lzf[k];
lzr[chl] = lzr[chr] = 0;
lzf[k] = -1;
}
if (lzr[k])
{
_swap(cl);
_swap(cr);
lzr[chl] ^= 1, lzr[chr] ^= 1;
lzr[k] = 0;
}
}
void init(int k, int l, int r)
{
if (r - l == 1)
{
node &p = tree[k];
_op(A[l], p, l, r);
}
else
{
int chl = (k << 1) + 1, chr = (k << 1) + 2, m = (l + r) >> 1;
init(chl, l, m);
init(chr, m, r);
tree[k] = merge(tree[chl], tree[chr], m - l, r - m);
}
}
void update(int op, int a, int b, int k, int l, int r)
{
node &p = tree[k];
if (a <= l && r <= b)
{
if (op < 2)
{
lzf[k] = op, lzr[k] = 0;
_op(op, p, l, r);
}
else
{
lzr[k] ^= 1;
_swap(p);
}
}
else if (a < r && l < b)
{
int chl = (k << 1) + 1, chr = (k << 1) + 2, m = (l + r) >> 1;
pushdown(k, chl, chr, l, r, m);
update(op, a, b, chl, l, m);
update(op, a, b, chr, m, r);
tree[k] = merge(tree[chl], tree[chr], m - l, r - m);
}
}
node query(int a, int b, int k, int l, int r)
{
if (a <= l && r <= b)
return tree[k];
int chl = (k << 1) + 1, chr = (k << 1) + 2, m = (l + r) >> 1;
pushdown(k, chl, chr, l, r, m);
if (b <= m)
return query(a, b, chl, l, m);
if (m <= a)
return query(a, b, chr, m, r);
node p1 = query(a, b, chl, l, m), p2 = query(a, b, chr, m, r);
return merge(p1, p2, m - max(a, l), min(b, r) - m);
}
int main()
{
scanf("%d%d", &N, &M);
for (int i = 0; i < N; i++)
scanf("%d", A + i);
init(0, 0, N);
memset(lzf, -1, sizeof(lzf));
memset(lzr, 0, sizeof(lzr));
while (M--)
{
int op, a, b;
scanf("%d%d%d", &op, &a, &b);
if (op <= 2)
update(op, a, b + 1, 0, 0, N);
else
{
node p = query(a, b + 1, 0, 0, N);
printf("%d\n", op == 3 ? p.tot[1] : p.cnt[1]);
}
}
return 0;
}