luoguP2253好一个一中腰鼓
用线段树维护三个值:
\(ll[x]\)表示\(x\)区间中包括左端点的最大长度
\(rr[x]\)表示\(x\)区间中包括右端点的最大长度
\(tr[x]\)表示\(x\)区间中的最大长度
\(tr[x]=\max(tr[x<<1],tr[x<<1|1])\)
如果\(a[mid]!=a[mid+1]\)
\(tr[x]=\max(tr[x],rr[x<<1]+ll[x<<1|1]);\)
\(rr[x]=rr[x<<1|1],ll[x]=ll[x<<1];\)
如果\(a[mid]!=a[mid+1]\)
如果\(ll[x]=mid-l+1\)
\(ll[x]+=ll[x<<1|1]\)
右边同理.
#include<bits/stdc++.h>
#define il inline
#define rg register
#define gi read<int>
using namespace std;
const int O = 2e5 + 10;
template<class TT>
il TT read() {
TT o = 0,fl = 1; char ch = getchar();
while (!isdigit(ch) && ch != '-') ch = getchar();
if (ch == '-') fl = -1, ch = getchar();
while (isdigit(ch)) o = o * 10 + ch - '0', ch = getchar();
return fl * o;
}
int a[O], n, m;
class SegmentTree {
private:
int tr[O << 2], ll[O << 2], rr[O << 2];
public:
il void Build(int x, int l, int r) {
ll[x] = rr[x] = tr[x] = 1;
if (l == r) return ;
int mid = l + r >> 1;
Build(x << 1, l, mid);
Build(x << 1 | 1, mid + 1, r);
}
il void Modify(int x, int l, int r, int pos) {
if (pos < l || pos > r) return ;
if (l == r) {
a[l] ^= 1;
return;
}
int mid = l + r >> 1;
Modify(x << 1, l, mid, pos);
Modify(x << 1 | 1, mid + 1, r, pos);
tr[x] = max(tr[x << 1], tr[x << 1 | 1]);
if (a[mid] ^ a[mid + 1])
tr[x] = max(tr[x], rr[x << 1] + ll[x << 1 | 1]);
ll[x] = ll[x << 1];
rr[x] = rr[x << 1 | 1];
if (ll[x] == mid - l + 1 && a[mid] ^ a[mid + 1])
ll[x] += ll[x << 1 | 1];
if (rr[x] == r - mid && a[mid] ^ a[mid + 1])
rr[x] += rr[x << 1];
}
il void Print() { printf("%d\n", tr[1]); }
}st;
int main() {
int n = gi(), m = gi();
st.Build(1, 1, n);
for(int i = 1; i <= m; ++i) {
int x = gi();
st.Modify(1, 1, n, x);
st.Print();
}
return 0;
}