题解:CF1620F Bipartite Array

题意:很简单了,不再赘述。

做法:

这个奇环太难描述了,看起来很困难,不过手玩之后很明显发现等同于没有一个长度 \(\ge 3\)\(LDS\)

那么我们很显然可以设计一个 \(O(n^3)\) 的 dp,\(dp_{i,j,k}\) 代表前 \(i\) 个数,最大值为 \(j\),作为 \(LDS\) 的第二个数的最大值为 \(k\),是否可行,直接枚举转移即可。

然后我们就要大力优化这个 dp。首先我们注意到这个 dp 是个 0/1 的 dp 太浪费了,同时我们注意到,当我们的 \(j\) 一定时,我们的 \(k\) 一定是越小越好的,因为这样就更难形成一个 3 长度的 \(LDS\),同理也可以得到 \(k\) 一定时,\(j\) 越小越好,所以我们可以随便压掉一位,将这一位计入答案里即可,这里我们状态中记录的是最大值,复杂度 \(O(n^2)\)

然后我们继续观察,我们发现这两维中一定有一维是由 \(p_{i-1}\) 贡献的!所以我们考虑记 \(f_{i,0/1,0/1}\) 代表在上面那个 \(O(n^2)\) dp 中是在状态那一维中还是在值中,如果在值中我们就记录的是最大值的最小值,去跑 dp 即可。

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 5;
int dp[maxn][2][2], n, p[maxn];
struct node {
	int i, x, y;
} pre[maxn][2][2];
void solve() {
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> p[i];
	for (int i = 0; i <= n; i++)	
		dp[i][0][0] = dp[i][0][1] = dp[i][1][0] = dp[i][1][1] = 2e9;
	dp[1][0][0] = dp[1][1][0] = -2e9;
	for (int i = 1; i < n; i++) {
		for (int x = 0; x <= 1; x++) {
			for (int y = 0; y <= 1; y++) {
				int mx, ed;
				if(y == 0)
					mx = p[i] * (x == 0 ? 1 : -1), ed = dp[i][x][y];
				if(y == 1)
					mx = dp[i][x][y], ed = p[i] * (x == 0 ? 1 : -1);
			//	cout << i << " " << mx << " " << ed << endl;
				for (int t = 0; t <= 1; t++) {
					int v = p[i + 1] * (t == 0 ? 1 : -1);
					if(ed > v)
						continue;
					if(mx > v) {
						if(dp[i + 1][t][1] > mx)
							dp[i + 1][t][1] = mx, pre[i + 1][t][1] = node{i, x, y};
					}
					if(mx <= v) {
					//	cout << mx << " " << v << endl;
						if(dp[i + 1][t][0] > ed)
							dp[i + 1][t][0] = ed, pre[i + 1][t][0] = node{i, x, y};
					}
				}
			}
		}
	}
	node p1 = {n, 0, 0};
	for (int x = 0; x <= 1; x++)
		for (int y = 0; y <= 1; y++)
			if(dp[n][x][y] != dp[0][0][0])
				p1 = node{n, x, y};
	if(dp[p1.i][p1.x][p1.y] == dp[0][0][0]) {
		cout << "NO" << endl;
		return ;
	}
	vector<int> ans;
	while(p1.i) {
		ans.push_back((p1.x == 0 ? 1 : -1) * p[p1.i]);
		p1 = pre[p1.i][p1.x][p1.y];
	}
	reverse(ans.begin(), ans.end());
	cout << "YES" << endl;
	for (int i = 0; i < n; i++)
		cout << ans[i] << " ";
	cout << endl;
}
int main() {
	int T; cin >> T;
	while(T--)
		solve();
	return 0;
}
posted @ 2025-07-25 20:04  LUlululu1616  阅读(12)  评论(0)    收藏  举报