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;
}

猜你喜欢

转载自www.cnblogs.com/lylyl/p/11681890.html