題目鏈接
題目解法
由題,不難得到一個 的動態規劃解法:記 表示是否存在一個長度爲 的合法 AB 序列,滿足存在 個 A ,且最後一個元素是 / 不是 A ,轉移顯然。
引理: 中,值爲真的部分是一個區間。
證明: 考慮歸納法,對於 的情況,引理顯然成立。
若 中存在至少一個數組值爲真的部分爲空,則引理顯然成立;
否則, 即 值爲真的部分均非空,有 。
討論 值爲真的部分是否爲空,可以發現 值爲真的部分對應的區間一定存在相交部分,或公共端點,由上述 DP 的轉移,可知引理成立。
由此,可以直接維護 值爲真的區間,省去 DP 的一維。
時間複雜度 。
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e6 + 5;
typedef long long ll;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); }
template <typename T> void read(T &x) {
x = 0; int f = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
x *= f;
}
char ans[MAXN];
int n, a[MAXN], b[MAXN];
pair <int, int> dp[MAXN][2];
void work(int pos, bool type, int lft) {
if (pos == 0) return;
ans[pos] = type + 'A', lft -= !type;
if (!type) {
if (a[pos] >= a[pos - 1] && dp[pos - 1][0].first <= lft && dp[pos - 1][0].second >= lft) work(pos - 1, 0, lft);
else work(pos - 1, 1, lft);
} else {
if (b[pos] >= a[pos - 1] && dp[pos - 1][0].first <= lft && dp[pos - 1][0].second >= lft) work(pos - 1, 0, lft);
else work(pos - 1, 1, lft);
}
}
void update(pair <int, int> &a, pair <int, int> b, bool type) {
if (type && b.first == n) return;
if (type) {
b.first++, b.second++;
chkmin(b.second, n);
}
chkmin(a.first, b.first);
chkmax(a.second, b.second);
}
int main() {
read(n);
for (int i = 1; i <= n * 2; i++)
read(a[i]);
for (int i = 1; i <= n * 2; i++)
read(b[i]);
for (int i = 0; i <= n * 2; i++)
dp[i][0] = dp[i][1] = make_pair(n, -n);
dp[0][0] = make_pair(0, 0);
for (int i = 1; i <= n * 2; i++) {
if (a[i] >= a[i - 1] && dp[i - 1][0] != make_pair(n, -n)) update(dp[i][0], dp[i - 1][0], 1);
if (a[i] >= b[i - 1] && dp[i - 1][1] != make_pair(n, -n)) update(dp[i][0], dp[i - 1][1], 1);
if (b[i] >= a[i - 1] && dp[i - 1][0] != make_pair(n, -n)) update(dp[i][1], dp[i - 1][0], 0);
if (b[i] >= b[i - 1] && dp[i - 1][1] != make_pair(n, -n)) update(dp[i][1], dp[i - 1][1], 0);
}
if (dp[n * 2][0].second != n && dp[n * 2][1].second != n) {
puts("-1");
return 0;
}
if (dp[n * 2][0].second == n) work(n * 2, 0, n);
else work(n * 2, 1, n);
printf("%s\n", ans + 1);
return 0;
}