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;
}
posted @ 2019-10-15 23:28  wuhan2005  阅读(100)  评论(0编辑  收藏  举报