CSP-S 2021 回文
ad-hoc
结论:移除 \(n\) 个元素后,这些元素的另一个的位置一定是连在一起的。
如果移除一个元素 \(x\),设 \(x\) 的另一个位置为 \(x'\),如果 \(x'\) 不与其它已经移除的元素的另一个位置相连,那么它们之间一定隔着一些元素,并且这些元素是后来移除的元素的另一个位置,那么后面这些元素后面就无法对应移除。
分别判断先移除 \(a\) 的开头元素和末尾元素,后面每一步优先考虑移除开头元素,如果两段无法移除,则无解;移除完 \(n\) 个元素后,根据移除的顺序,剩下的顺序就能确定了。
时间复杂度为 \(O(n)\)。
#include <bits/stdc++.h>
const int N = 500005;
int n, ano[N * 2];
int a[N * 2], b[N];
std::bitset<N * 2> s;
bool exist(int x) {
return (s[ano[x] - 1] || s[ano[x] + 1]) && !s[x];
}
bool checkL() {
s.reset();
s[ano[1]] = 1;
std::string res = "L";
std::vector<int> pos = {1};
int l = 2, r = n * 2;
for (int i = 2; i <= n; i++) {
if (exist(l)) {
res.push_back('L');
pos.push_back(l);
s[ano[l]] = 1, l++;
} else if (exist(r)) {
res.push_back('R');
pos.push_back(r);
s[ano[r]] = 1, r--;
} else {
return false;
}
}
std::reverse(pos.begin(), pos.end());
for (auto x : pos) {
if (s[ano[x] + 1]) {
res.push_back('L');
} else if (s[ano[x] - 1]) {
res.push_back('R');
} else {
res.push_back('L');
}
s[ano[x]] = 0;
}
std::cout << res << '\n';
return true;
}
bool checkR() {
s.reset();
s[ano[n * 2]] = 1;
std::string res = "R";
std::vector<int> pos = {n * 2};
int l = 1, r = n * 2 - 1;
for (int i = 2; i <= n; i++) {
if (exist(l)) {
res.push_back('L');
pos.push_back(l);
s[ano[l]] = 1, l++;
} else if (exist(r)) {
res.push_back('R');
pos.push_back(r);
s[ano[r]] = 1, r--;
} else {
return false;
}
}
std::reverse(pos.begin(), pos.end());
for (auto x : pos) {
if (s[ano[x] + 1]) {
res.push_back('L');
} else if (s[ano[x] - 1]) {
res.push_back('R');
} else {
res.push_back('L');
}
s[ano[x]] = 0;
}
std::cout << res << '\n';
return true;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t;
std::cin >> t;
while (t--) {
std::cin >> n;
for (int i = 1; i <= n * 2; i++) {
std::cin >> a[i];
if (b[a[i]]) {
ano[i] = b[a[i]];
ano[b[a[i]]] = i;
}
b[a[i]] = i;
}
if (!checkL() && !checkR())
std::cout << -1 << '\n';
for (int i = 1; i <= n * 2; i++)
a[i] = 0, ano[i] = 0;
for (int i = 1; i <= n; i++) b[i] = 0;
}
return 0;
}