一,题目
# [SCOI2010] 序列操作
## 题目描述
lxhgww 最近收到了一个 $01$ 序列,序列里面包含了 $n$ 个数,下标从 $0$ 开始。这些数要么是 $0$,要么是 $1$,现在对于这个序列有五种变换操作和询问操作:
- `0 l r` 把 $[l, r]$ 区间内的所有数全变成 $0$
- `1 l r` 把 $[l, r]$ 区间内的所有数全变成 $1$
- `2 l r` 把 $[l,r]$ 区间内的所有数全部取反,也就是说把所有的 $0$ 变成 $1$,把所有的 $1$ 变成 $0$
- `3 l r` 询问 $[l, r]$ 区间内总共有多少个 $1$
- `4 l r` 询问 $[l, r]$ 区间内最多有多少个连续的 $1$
对于每一种询问操作,lxhgww 都需要给出回答,聪明的程序员们,你们能帮助他吗?
## 输入格式
第一行两个正整数 $n,m$,表示序列长度与操作个数。
第二行包括 $n$ 个数,表示序列的初始状态。
接下来 $m$ 行,每行三个整数,表示一次操作。
## 输出格式
对于每一个询问操作,输出一行一个数,表示其对应的答案。
## 样例 #1
### 样例输入 #1
```
10 10
0 0 0 1 1 0 1 0 1 1
1 0 2
3 0 5
2 2 2
4 0 4
0 3 6
2 3 7
4 2 8
1 0 5
0 5 6
3 3 9
```
### 样例输出 #1
```
5
2
6
5
```
## 提示
【数据范围】
对于 $30\%$ 的数据,$1\le n,m \le 1000$;
对于$100\%$ 的数据,$1\le n,m \le 10^5$。
二,代码
#include<iostream>
using namespace std;
const int MAXN = 1e5 + 5;
struct TREE
{
int SUM[2], LSUM[2], RSUM[2], MAX[2];
}tree[MAXN << 2] = { 0 };
int fir[MAXN << 2], sec[MAXN << 2], thi[MAXN << 2], arr[MAXN << 2];
int ls(int p) { return p << 1; }
int rs(int p) { return p << 1 | 1; }
void pu(TREE& p, const TREE& lsp, const TREE& rsp)
{
for (int i = 0; i <= 1; ++i)
{
p.LSUM[i] = lsp.LSUM[i] + (lsp.SUM[i] + lsp.SUM[i ^ 1] == lsp.LSUM[i] ? rsp.LSUM[i] : 0);
p.RSUM[i] = rsp.RSUM[i] + (rsp.SUM[i] + rsp.SUM[i ^ 1] == rsp.RSUM[i] ? lsp.RSUM[i] : 0);
p.SUM[i] = lsp.SUM[i] + rsp.SUM[i];
p.MAX[i] = max(max(rsp.MAX[i], lsp.MAX[i]), lsp.RSUM[i] + rsp.LSUM[i]);
}
}
void at(int p, int pl, int pr, int a, int b, int c)
{
if (a != 0 || (sec[p] == 1 && c != 0))
{
tree[p].SUM[1] = tree[p].LSUM[1] = tree[p].RSUM[1] = tree[p].MAX[1] = 0;
tree[p].SUM[0] = tree[p].LSUM[0] = tree[p].RSUM[0] = tree[p].MAX[0] = pr - pl + 1;
sec[p] = 0, thi[p] = 0, fir[p] = 1;
}
else if (b != 0 || (fir[p] == 1 && c != 0))
{
tree[p].SUM[1] = tree[p].LSUM[1] = tree[p].RSUM[1] = tree[p].MAX[1] = pr - pl + 1;
tree[p].SUM[0] = tree[p].LSUM[0] = tree[p].RSUM[0] = tree[p].MAX[0] = 0;
fir[p] = 0, thi[p] = 0, sec[p] = 1;
}
else if (c != 0)
{
swap(tree[p].LSUM[0], tree[p].LSUM[1]), swap(tree[p].MAX[0], tree[p].MAX[1]);
swap(tree[p].RSUM[0], tree[p].RSUM[1]), swap(tree[p].SUM[0], tree[p].SUM[1]);
fir[p] = sec[p] = 0, thi[p] = (thi[p] + 1) & 1;
}
}
void pd(int p, int pl, int pr)
{
int mid = pl + pr >> 1;
at(ls(p), pl, mid, fir[p], sec[p], thi[p]), at(rs(p), mid + 1, pr, fir[p], sec[p], thi[p]);
fir[p] = sec[p] = thi[p] = 0;
}
void b(int p, int pl, int pr)
{
if (pl == pr)
{
tree[p].LSUM[arr[pl]] = tree[p].MAX[arr[pl]] = tree[p].RSUM[arr[pl]] = tree[p].SUM[arr[pl]] = 1;
tree[p].LSUM[arr[pl] ^ 1] = tree[p].MAX[arr[pl] ^ 1] = tree[p].RSUM[arr[pl] ^ 1] = tree[p].SUM[arr[pl] ^ 1] = 0;
return;
}
int mid = pl + pr >> 1;
b(ls(p), pl, mid), b(rs(p), mid + 1, pr);
pu(tree[p], tree[ls(p)], tree[rs(p)]);
}
void ch(int p, int pl, int pr, int L, int R, int a, int b, int c)
{
pd(p, pl, pr);
if (L <= pl && pr <= R) { at(p, pl, pr, a, b, c); return; }
int mid = pl + pr >> 1;
if (L <= mid) ch(ls(p), pl, mid, L, R, a, b, c);
if (R > mid) ch(rs(p), mid + 1, pr, L, R, a, b, c);
ls(p), rs(p);
pu(tree[p], tree[ls(p)], tree[rs(p)]);
}
TREE qu(int p, int pl, int pr, int L, int R)
{
pd(p, pl, pr);
if (L <= pl && pr <= R) { return tree[p]; }
int mid = pl + pr >> 1;
if (L <= mid && mid < R)
{
TREE ans = { 0 };
pu(ans, qu(ls(p), pl, mid, L, R), qu(rs(p), mid + 1, pr, L, R));
return ans;
}
else if (L <= mid) return qu(ls(p), pl, mid, L, R);
else return qu(rs(p), mid + 1, pr, L, R);
}
int main()
{
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; ++i) cin >> arr[i];
b(1, 1, n);
for (int i = 1; i <= m; ++i)
{
int op, x, y;
cin >> op >> x >> y;
if (op == 0) ch(1, 1, n, x + 1, y + 1, 1, 0, 0);
if (op == 1) ch(1, 1, n, x + 1, y + 1, 0, 1, 0);
if (op == 2) ch(1, 1, n, x + 1, y + 1, 0, 0, 1);
if (op == 3) cout << qu(1, 1, n, x + 1, y + 1).SUM[1] << '\n';
if (op == 4) cout << qu(1, 1, n, x + 1, y + 1).MAX[1] << '\n';
}
return 0;
}