好久不见~ 这里是某鸽子博主的突然更新 (ෆ´ ˘ `ෆ)♡
比赛链接:https://codeforces.com/contest/1494
A. ABC String
题解
字符串首端的字母一定是用 '(' 代替,末端的字母一定是用 ')' 代替,第三类字符枚举 '(' , ')' 两种情况即可。
代码
#include <bits/stdc++.h>
using namespace std;
bool check(const string& s) {
int l = 0;
for (char c : s) {
if (c == '(') {
++l;
} else {
--l;
}
if (l < 0) {
return false;
}
}
return l == 0;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
string s;
cin >> s;
bool ok = false;
for (char rep_c : {'(', ')'}) {
string t(s);
for (char& c : t) {
if (c == s.front()) {
c = '(';
} else if (c == s.back()) {
c = ')';
} else {
c = rep_c;
}
}
ok or_eq check(t);
}
cout << (ok ? "YES" : "NO") << "
";
}
return 0;
}
B. Berland Crossword
题解
枚举四个角的摆放状态即可,可以用状压,也可以用dfs。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
int n, up, rt, dw, lf;
cin >> n >> up >> rt >> dw >> lf;
bool ok = false;
for (int i = 0; i < (1 << 4); i++) {
int u = up, r = rt, d = dw, l = lf;
if (i >> 3 & 1) {
--l, --u;
}
if (i >> 2 & 1) {
--r, --u;
}
if (i >> 1 & 1) {
--l, --d;
}
if (i >> 0 & 1) {
--r, --d;
}
if (min({u, r, d, l}) >= 0 and max({u, r, d, l}) <= n - 2) {
ok = true;
}
}
cout << (ok ? "YES" : "NO") << "
";
}
return 0;
}
C. 1D Sokoban
题解
以正数的情况为例,每次枚举当前特殊点为推箱子的终点,二分查找前面有多少个箱子及特殊点,当前特殊点之后与箱子重合的特殊点个数可以预处理。
负数取绝对值反转后与正数情况相同。
代码
#include <bits/stdc++.h>
using namespace std;
int cal (const auto& a, const auto& b) {
int m = b.size();
vector<int> dp(m); //当前特殊点及右侧有多少与箱子位置重合
for (int i = m - 1; i >= 0; i--) {
if (binary_search(a.begin(), a.end(), b[i])) {
dp[i] = 1;
}
if (i + 1 < m) {
dp[i] += dp[i + 1];
}
}
int res = 0;
for (int i = 0; i < m; i++) { //枚举特殊点为推箱子的终点
int num = upper_bound(a.begin(), a.end(), b[i]) - lower_bound(a.begin(), a.end(), 0); //当前特殊点及左侧有多少个箱子
int l = b[i] - (num - 1); //第一个箱子的位置
int r = b[i]; //最后一个箱子的位置
int in_seg = upper_bound(b.begin(), b.end(), r) - lower_bound(b.begin(), b.end(), l); //箱子间有多少个特殊点
int idx = upper_bound(b.begin(), b.end(), r) - b.begin(); //最后一个箱子位置右侧的特殊点的下标
res = max(res, min(num, in_seg) + (0 <= idx and idx < m ? dp[idx] : 0));
}
return res;
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
int n, m;
cin >> n >> m;
vector<int> pos_a, neg_a;
for (int i = 0; i < n; i++) {
int x;
cin >> x;
if (x > 0) {
pos_a.push_back(x);
} else {
neg_a.push_back(-x);
}
}
vector<int> pos_b, neg_b;
for (int i = 0; i < m; i++) {
int x;
cin >> x;
if (x > 0) {
pos_b.push_back(x);
} else {
neg_b.push_back(-x);
}
}
reverse(neg_a.begin(), neg_a.end());
reverse(neg_b.begin(), neg_b.end());
cout << cal(pos_a, pos_b) + cal(neg_a, neg_b) << "
";
}
return 0;
}