線段樹結點結構:
bl,br,ba 分別表示包括左端點黑石子的連續長度,包括右端點黑石子的連續長度,區間中黑石子的最大連續長度
wl,wr,wa 分別表示包括左端點白石子的連續長度,包括右端點白石子的連續長度,區間中白石子的最大連續長度
ta 表示結點的子結點是否需要更新
對於區間[a,b]的更新操作:
首先找到線段樹中相應的區間,將黑變白、白變黑實際上就是把 bl,br,ba 和 wl,wr,wa 互換。但是不對這個區間的子區間再進行更新(如果這樣做的話時間複雜度就會達到O(n)),而是將 ta xor 1,記下該區間的子區間沒有被跟新,下次如果用到(更新或者查詢)該區間的子區間再對其進行更新。對包含被更新區間的所有區間進行更新。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <memory.h>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <iostream>
using namespace std;
const int N = 100005;
struct Node {
int l, r;
int bl, br, ba;
int wl, wr, wa;
int ta;
} st[N*3];
int ary[N];
void Update(int p) {
int lp = p * 2, rp = p * 2 + 1;
if ((st[p].ba = max(st[lp].ba, st[rp].ba)) < st[lp].br + st[rp].bl)
st[p].ba = st[lp].br + st[rp].bl;
if ((st[p].wa = max(st[lp].wa, st[rp].wa)) < st[lp].wr + st[rp].wl)
st[p].wa = st[lp].wr + st[rp].wl;
int ll = st[lp].r - st[lp].l + 1, rl = st[rp].r - st[rp].l + 1;
st[p].bl = st[lp].bl; if (st[lp].bl == ll) st[p].bl += st[rp].bl;
st[p].wl = st[lp].wl; if (st[lp].wl == ll) st[p].wl += st[rp].wl;
st[p].br = st[rp].br; if (st[rp].br == rl) st[p].br += st[lp].br;
st[p].wr = st[rp].wr; if (st[rp].wr == rl) st[p].wr += st[lp].wr;
}
void Change(int p) {
swap(st[p].bl, st[p].wl);
swap(st[p].br, st[p].wr);
swap(st[p].ba, st[p].wa);
st[p].ta ^= 1;
}
void Build(int l, int r, int p) {
st[p].l = l; st[p].r = r; st[p].ta = 0;
if (l == r) {
if (ary[l]) {
st[p].bl = st[p].br = st[p].ba = 1;
st[p].wl = st[p].wr = st[p].wa = 0;
} else {
st[p].wl = st[p].wr = st[p].wa = 1;
st[p].bl = st[p].br = st[p].ba = 0;
}
return;
}
int m = (l + r) / 2;
Build(l, m, p * 2);
Build(m + 1, r, p * 2 + 1);
Update(p);
}
void Update(int l, int r, int p) {
if (st[p].l == l && st[p].r == r) {
Change(p);
return;
}
if (st[p].ta) {
Change(p * 2);
Change(p * 2 + 1);
st[p].ta ^= 1;
}
int m = (st[p].l + st[p].r) / 2;
if (r <= m) Update(l, r, p * 2);
else if (l > m) Update(l, r, p * 2 + 1);
else Update(l, m, p * 2), Update(m + 1, r, p * 2 + 1);
Update(p);
}
int Query(int l, int r, int p) {
// printf("%d %d %d\n", p, st[p].ba, st[p].ta);
if (st[p].l == l && st[p].r == r) {
return st[p].ba;
}
if (st[p].ta) {
Change(p * 2);
Change(p * 2 + 1);
st[p].ta ^= 1;
}
int m = (st[p].l + st[p].r) / 2;
if (r <= m) return Query(l, r, p * 2);
else if (l > m) return Query(l, r, p * 2 + 1);
else {
int lr = Query(l, m, p * 2);
int rr = Query(m + 1, r, p * 2 + 1);
return max(max(min(st[p*2].br, lr) + min(st[p*2+1].bl, rr), lr), rr);
}
}
int main() {
int n, m, i, a, b, c;
while (scanf("%d", &n) != EOF) {
for (i = 1; i <= n; i++)
scanf("%d", ary + i);
Build(1, n, 1);
scanf("%d", &m);
for (i = 0; i < m; i++) {
scanf("%d %d %d", &a, &b, &c);
if (a) Update(b, c, 1);
else printf("%d\n", Query(b, c, 1));
}
}
return 0;
}