题解:ARC230B Chmax and Chmin
没做明白。
考虑倒着做,每次尝试撤销一个 \(\operatorname{chkmax}\) 或者 \(\operatorname{chkmin}\) 操作。考虑维护当前 \(b_i\) 合法的取值范围为 \([L,R]\),撤销一次对 \(v\) 做 \(\operatorname{chkmax}\) 的操作后,新的取值范围 \([L',R']\) 为
类似地,撤销一次对 \(v\) 做 \(\operatorname{chkmin}\) 的操作后,新的取值范围 \([L',R']\) 为
因此最终 \(b_i\) 的取值范围 \([L,R]\) 满足 \(L\in\{1,b_i\},R\in\{b_i,n\}\)。
考虑如果要撤销一个对 \([l,r]\) 做 \(\operatorname{chkmax}\) 的操作,则撤销前对于每个 \(l\leq i\leq r\),要有 \(R_i\geq X_{r-l+1}\);撤销后,若 \(L_i=b_i\leq X_{r-l+1}\),则 \(L_i\gets 1\)。同理,若撤销 \(\operatorname{chkmin}\) 操作,则撤销前要有 \(L_i\leq Y_{r-l+1}\);撤销后,若 \(R_i=b_i\geq Y_{r-l+1}\),则 \(R_i\gets n\)。
有效的操作必然会令 \(L_i\gets 1\) 或者令 \(R_i\gets n\),因此至多只有 \(2n\) 次有效操作。用一个队列维护当前所有合法的操作,每次取出队头操作撤销,然后将变得合法的操作加到队尾。具体来说,对于每个区间 \([l,r]\),维护 \(cmx_{l,r}=\sum_{i=l}^r[R_i=b_i<X_{r-l+1}]\),\(cmn_{l,r}=\sum_{i=l}^r[L_i=b_i>Y_{r-l+1}]\),将 \(cmx/cmn=0\) 的区间对应操作就是合法的。
时间复杂度为 \(\mathcal{O}(n^3)\)。
代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using i128 = __int128;
using ui = unsigned int;
using ull = unsigned long long;
using u128 = unsigned __int128;
using ld = long double;
using pii = pair<int, int>;
const int MAXN = 405;
template<typename T> T lowbit(T x) { return x & -x; }
template<typename T> void chkMin(T &x, T y) { x = y < x ? y : x; }
template<typename T> void chkMax(T &x, T y) { x = x < y ? y : x; }
constexpr int lg2(ll x) { return 63 ^ __builtin_clzll(x); }
constexpr ll bitCeil(ll x) { return x == 1 ? 1ll : 1ll << lg2(x - 1) + 1; }
int tc, n, X[MAXN], Y[MAXN], a[MAXN], b[MAXN];
int cmx[MAXN][MAXN], cmn[MAXN][MAXN];
bool L[MAXN], R[MAXN];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> tc;
while (tc--) {
cin >> n;
for (int i = 1; i <= n; ++i) cin >> X[i];
for (int i = 1; i <= n; ++i) cin >> Y[i];
for (int i = 1; i <= n; ++i) cin >> a[i];
for (int i = 1; i <= n; ++i) cin >> b[i];
queue<tuple<int, int, int>> Q;
vector<tuple<int, int, int>> oper;
fill(L + 1, L + n + 1, false);
fill(R + 1, R + n + 1, false);
for (int l = 1; l <= n; ++l) {
for (int r = l; r <= n; ++r) {
cmx[l][r] = cmn[l][r] = 0;
for (int i = l; i <= r; ++i) {
cmx[l][r] += b[i] < X[r - l + 1];
cmn[l][r] += b[i] > Y[r - l + 1];
}
if (!cmx[l][r]) Q.emplace(l, r, 0);
if (!cmn[l][r]) Q.emplace(l, r, 1);
}
}
while (!Q.empty()) {
auto [l, r, tp] = Q.front();
Q.pop();
bool ok = false;
if (!tp) {
for (int i = l; i <= r; ++i) {
if (!L[i] && b[i] <= X[r - l + 1]) {
L[i] = ok = true;
for (int x = 1; x <= i; ++x) {
for (int y = i; y <= n; ++y) {
if (b[i] > Y[y - x + 1] && !--cmn[x][y]) Q.emplace(x, y, 1);
}
}
}
}
} else {
for (int i = l; i <= r; ++i) {
if (!R[i] && b[i] >= Y[r - l + 1]) {
R[i] = ok = true;
for (int x = 1; x <= i; ++x) {
for (int y = i; y <= n; ++y) {
if (b[i] < X[y - x + 1] && !--cmx[x][y]) Q.emplace(x, y, 0);
}
}
}
}
}
if (ok) oper.emplace_back(l, r, tp);
}
bool ok = true;
for (int i = 1; i <= n; ++i) {
int l = L[i] ? 1 : b[i], r = R[i] ? n : b[i];
if (a[i] < l || a[i] > r) {
ok = false;
break;
}
}
if (!ok) {
cout << "-1\n";
} else {
reverse(oper.begin(), oper.end());
cout << oper.size() << '\n';
for (auto [l, r, tp] : oper) {
if (!tp) cout << "chmax " << l << ' ' << r << '\n';
else cout << "chmin " << l << ' ' << r << '\n';
}
}
}
return 0;
}

浙公网安备 33010602011771号