题解:SP31938 QUERYIT - SLIS
经典线段树题。
\(01\) 序列的不下降子序列一定是 \(00\cdots 0011\cdots 11\) 的形式,由于需要区间取反操作,我们也必须把不上升子序列 \(11\cdots 1100\cdots 00\) 的信息维护上。
线段树维护 \(\operatorname{cnt0}(u),\operatorname{cnt1}(u),\operatorname{ans01}(u),\operatorname{ans10}(u)\) 依次表示节点 \(u\) 对应区间内 \(0\) 的个数、\(1\) 的个数、最长 \(00\cdots 0011\cdots 11\) 子序列长度、最长 \(11\cdots 1100\cdots 00\) 子序列长度。
设节点 \(u\) 的左右儿子分别为 \(\operatorname{lc}(u),\operatorname{rc}(u)\),则可以按照如下方式合并子节点信息:
\[\begin{aligned}
\operatorname{cnt0}(u)&=\operatorname{cnt0}(\operatorname{lc}(u))+\operatorname{cnt0}(\operatorname{rc}(u))\\
\operatorname{cnt1}(u)&=\operatorname{cnt1}(\operatorname{lc}(u))+\operatorname{cnt1}(\operatorname{rc}(u))\\
\operatorname{ans01}(u)&=\max\{\operatorname{ans01}(\operatorname{lc}(u))+\operatorname{cnt1}(\operatorname{rc}(u)),\operatorname{cnt0}(\operatorname{lc}(u))+\operatorname{ans01}(\operatorname{rc}(u))\}\\
\operatorname{ans10}(u)&=\max\{\operatorname{ans10}(\operatorname{lc}(u))+\operatorname{cnt0}(\operatorname{rc}(u)),\operatorname{cnt1}(\operatorname{lc}(u))+\operatorname{ans10}(\operatorname{rc}(u))\}\\
\end{aligned}
\]
维护区间反转标记,当节点对应区间整个被反转时,只需打标记并交换 \(\operatorname{cnt0}(u)\) 与 \(\operatorname{cnt1}(u)\)、\(\operatorname{ans01}(u)\) 与 \(\operatorname{ans10}(u)\) 即可。
时间复杂度 \(O(n+m\log n)\)。
//By: OIer rui_er
#include <bits/stdc++.h>
#define rep(x, y, z) for(int x = (y); x <= (z); ++x)
#define per(x, y, z) for(int x = (y); x >= (z); --x)
#define debug(format...) fprintf(stderr, format)
#define fileIO(s) do {freopen(s".in", "r", stdin); freopen(s".out", "w", stdout);} while(false)
#define endl '\n'
using namespace std;
typedef long long ll;
mt19937 rnd(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count());
int randint(int L, int R) {
uniform_int_distribution<int> dist(L, R);
return dist(rnd);
}
template<typename T> void chkmin(T& x, T y) {if(y < x) x = y;}
template<typename T> void chkmax(T& x, T y) {if(x < y) x = y;}
template<int mod>
inline unsigned int down(unsigned int x) {
return x >= mod ? x - mod : x;
}
template<int mod>
struct Modint {
unsigned int x;
Modint() = default;
Modint(unsigned int x) : x(x) {}
friend istream& operator>>(istream& in, Modint& a) {return in >> a.x;}
friend ostream& operator<<(ostream& out, Modint a) {return out << a.x;}
friend Modint operator+(Modint a, Modint b) {return down<mod>(a.x + b.x);}
friend Modint operator-(Modint a, Modint b) {return down<mod>(a.x - b.x + mod);}
friend Modint operator*(Modint a, Modint b) {return 1ULL * a.x * b.x % mod;}
friend Modint operator/(Modint a, Modint b) {return a * ~b;}
friend Modint operator^(Modint a, int b) {Modint ans = 1; for(; b; b >>= 1, a *= a) if(b & 1) ans *= a; return ans;}
friend Modint operator~(Modint a) {return a ^ (mod - 2);}
friend Modint operator-(Modint a) {return down<mod>(mod - a.x);}
friend Modint& operator+=(Modint& a, Modint b) {return a = a + b;}
friend Modint& operator-=(Modint& a, Modint b) {return a = a - b;}
friend Modint& operator*=(Modint& a, Modint b) {return a = a * b;}
friend Modint& operator/=(Modint& a, Modint b) {return a = a / b;}
friend Modint& operator^=(Modint& a, int b) {return a = a ^ b;}
friend Modint& operator++(Modint& a) {return a += 1;}
friend Modint operator++(Modint& a, int) {Modint x = a; a += 1; return x;}
friend Modint& operator--(Modint& a) {return a -= 1;}
friend Modint operator--(Modint& a, int) {Modint x = a; a -= 1; return x;}
friend bool operator==(Modint a, Modint b) {return a.x == b.x;}
friend bool operator!=(Modint a, Modint b) {return !(a == b);}
};
const int N = 1e5 + 5;
int n, m, a[N];
string s;
struct Node {
int cnt0, cnt1, ans01, ans10;
Node(int cnt0 = 0, int cnt1 = 0, int ans01 = 0, int ans10 = 0):
cnt0(cnt0), cnt1(cnt1), ans01(ans01), ans10(ans10) {}
friend Node operator+(Node a, Node b) {
return Node(
a.cnt0 + b.cnt0,
a.cnt1 + b.cnt1,
max(a.ans01 + b.cnt1, a.cnt0 + b.ans01),
max(a.ans10 + b.cnt0, a.cnt1 + b.ans10)
);
}
friend Node operator-(Node a) {
return Node(a.cnt1, a.cnt0, a.ans10, a.ans01);
}
};
struct SegTree {
Node t[N << 2];
int tag[N << 2];
#define lc(u) (u << 1)
#define rc(u) (u << 1 | 1)
void build(int* a, int u, int l, int r) {
if(l == r) {
t[u] = Node(a[l] == 0, a[l] == 1, 1, 1);
return;
}
int mid = (l + r) >> 1;
build(a, lc(u), l, mid);
build(a, rc(u), mid + 1, r);
t[u] = t[lc(u)] + t[rc(u)];
}
void pushtag(int u) {
tag[u] ^= 1;
t[u] = -t[u];
}
void pushdown(int u) {
if(!tag[u]) return;
pushtag(lc(u));
pushtag(rc(u));
tag[u] = 0;
}
void modify(int u, int l, int r, int ql, int qr) {
if(ql <= l && r <= qr) {
pushtag(u);
return;
}
pushdown(u);
int mid = (l + r) >> 1;
if(ql <= mid) modify(lc(u), l, mid, ql, qr);
if(qr > mid) modify(rc(u), mid + 1, r, ql, qr);
t[u] = t[lc(u)] + t[rc(u)];
}
#undef lc
#undef rc
}sgt;
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n >> m >> s;
rep(i, 1, n) a[i] = s[i - 1] - '0';
sgt.build(a, 1, 1, n);
while(m--) {
int op;
cin >> op;
if(op == 0) {
int l, r;
cin >> l >> r;
sgt.modify(1, 1, n, l, r);
}
else cout << sgt.t[1].ans01 << endl;
}
return 0;
}

浙公网安备 33010602011771号