题解:P11710 「KTSC 2020 R2」一二三
设
设
观察匹配的性质,发现
那么我们容易扫描求出
这并不充分。现在给每对匹配分配一个
我们先求出最大的
使用 Hall 定理,相当于对于每个区间
枚举
那么我们通过观察可以得出区间内
求出
可以拆成
得到一组
代码中变量名会有所差异。
ll n, a[maxn], b[maxn], m[4], ulim, vlim, slim, u, v;
set <ll> st; vector <ll> vec[4];
void maximize(vector <ll> A) {
n = A.size();
for(ll i = 0; i < n; i++) a[i + 1] = A[i];
vec[1].pb(0), vec[2].pb(0), vec[3].pb(0);
for(ll i = 1; i <= n; i++)
b[i] = ++m[a[i]], vec[a[i]].pb(i);
ulim = vlim = slim = min(min(m[1], m[3]), m[2]);
for(ll i = 1, lst1 = 0, lst3 = 0; i <= n; i++)
if(a[i] == 1) {
if(lst3) chkmin(ulim, b[i] + m[3] - lst3 - 1);
lst1 = b[i];
} else if(a[i] == 3) {
if(lst1) chkmin(vlim, b[i] + m[1] - lst1 - 1);
lst3 = b[i];
}
for(ll l = 1; l <= n; l++) {
ll cnt = 0, fir1 = 0, fir3 = 0, lst1 = 0, lst3 = 0;
for(ll r = l; r <= n; r++) {
if(a[r] == 2) ++cnt;
else if(a[r] == 1) {
fir1 || (fir1 = b[r]);
lst1 = b[r];
} else {
fir3 || (fir3 = b[r]);
lst3 = b[r];
}
if(!fir1 || !fir3) continue;
ll u0 = fir1 + m[3] - lst3 - 1, v0 = fir3 + m[1] - lst1 - 1;
chkmin(ulim, u0 + cnt), chkmin(vlim, v0 + cnt);
chkmin(slim, u0 + v0 + cnt);
}
}
u = min(ulim, slim), v = min(vlim, slim - u);
for(ll i = 1; i <= n; i++) {
if(a[i] == 2) st.insert(i);
else if(a[i] == 1) {
if(m[1] - b[i] + 1 <= v) {
auto it = st.lower_bound(vec[3][b[i] - m[1] + v]);
answer(vec[3][b[i] - m[1] + v] - 1, *it - 1, i - 1);
st.erase(it);
}
} else {
if(m[3] - b[i] + 1 <= u) {
auto it = st.lower_bound(vec[1][b[i] - m[3] + u]);
answer(vec[1][b[i] - m[3] + u] - 1, *it - 1, i - 1);
st.erase(it);
}
}
}
}