题解:ARC230B Chmax and Chmin

没做明白。

考虑倒着做,每次尝试撤销一个 \(\operatorname{chkmax}\) 或者 \(\operatorname{chkmin}\) 操作。考虑维护当前 \(b_i\) 合法的取值范围为 \([L,R]\),撤销一次对 \(v\) 做 \(\operatorname{chkmax}\) 的操作后,新的取值范围 \([L',R']\) 为

\[[L',R']=\begin{cases} \varnothing &\text{if }v>R\\ [1,R]&\text{if }L\leq v\leq R\\ [L,R]&\text{if }v<L \end{cases} \]

类似地,撤销一次对 \(v\) 做 \(\operatorname{chkmin}\) 的操作后,新的取值范围 \([L',R']\) 为

\[[L',R']=\begin{cases} \varnothing &\text{if }v<L\\ [L,n]&\text{if }L\leq v\leq R\\ [L,R]&\text{if }v>R \end{cases} \]

因此最终 \(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;
}
posted @ 2026-09-22 21:13  P2441M  阅读(9)  评论(0)    收藏  举报