A. Special Characters
构造。
形如 \(A\) 和 \(B\) 这类单个字符构成的字符串对答案的贡献为 \(0\),而 \(AA\) 和 \(AAAA\) 这类多个相同字符构成的字符串对答案的贡献固定为 \(2\),则无法构造出奇数值,由第二类字符串拼接即可构造出偶数值。
时间复杂度:\(O(n)\) 。
#include <bits/stdc++.h>
using namespace std;
#define cctie ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define all(x) x.begin(), x.end()
#define ALL(x) x.begin() + 1, x.end()
using i64 = long long;
void solve() {
int n;
cin >> n;
if (n & 1) {
cout << "NO\n";
} else {
cout << "YES\n";
string ans;
for (int i = 0; i < n / 2; i++) {
ans.push_back('A' + i);
ans.push_back('A' + i);
}
cout << ans << '\n';
}
}
void prework() {
}
int main() {
cctie;
prework();
int T;
cin >> T;
while (T--) {
solve();
}
return 0;
}
B. Array Fix
枚举/贪心。
枚举:能执行操作的一定是两位数,且该操作一定会使被操作数分裂成两个个位数,则当我们对第 \(i\) 个数执行操作后,前 \(i - 1\) 个数中的两位数也得执行操作(因为两位数一定大于个位数),即执行操作的数一定为其前缀,所以枚举操作的前缀,再判断是否非递减即可。
贪心:当第 \(i\) 个数能分裂且分裂后不影响前 \(i\) 个数的非递减性质,则分裂更优(为后面的数分裂留出空间)。
时间复杂度:枚举 \(O(n^2)\),贪心 \(O(n)\) 。
#include <bits/stdc++.h>
using namespace std;
#define cctie ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define all(x) x.begin(), x.end()
#define ALL(x) x.begin() + 1, x.end()
using i64 = long long;
void solve() {
int n;
cin >> n;
vector<int> a(n + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
bool ans = false;
for (int i = 0; i <= n; i++) {
vector<int> b;
for (int j = 1; j <= n; j++) {
if (j <= i && a[j] >= 10) {
b.push_back(a[j] / 10);
b.push_back(a[j] % 10);
} else {
b.push_back(a[j]);
}
}
int m = b.size();
bool f = true;
for (int i = 1; i < m; i++) {
if (b[i] < b[i - 1]) {
f = false;
}
}
if (f) {
ans = true;
}
}
if (ans) {
cout << "YES\n";
} else {
cout << "NO\n";
}
}
void prework() {
}
int main() {
cctie;
prework();
int T;
cin >> T;
while (T--) {
solve();
}
return 0;
}
C. Arrow Path
搜索 。
按题中的行动方式进行 \(bfs\) 即可。
时间复杂度:\(O(n)\) 。
#include <bits/stdc++.h>
using namespace std;
#define cctie ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define all(x) x.begin(), x.end()
#define ALL(x) x.begin() + 1, x.end()
using i64 = long long;
void solve() {
int n;
cin >> n;
vector<vector<char>> a(3, vector<char>(n + 1));
for (int i = 1; i <= 2; i++) {
for (int j = 1; j <= n; j++) {
cin >> a[i][j];
}
}
vector<vector<bool>> st(3, vector<bool>(n + 1));
queue<array<int, 2>> q;
q.push({1, 1});
st[1][1] = true;
vector<int> dx = {-1, 0, 0, 1}, dy = {0, 1, -1, 0};
auto is_legal = [&](int x, int y)->bool {
return 1 <= x && x <= 2 && 1 <= y && y <= n;
};
while (!q.empty()) {
auto [x, y] = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
int nx = x + dx[i], ny = y + dy[i];
if (is_legal(nx, ny)) {
if (a[nx][ny] == '<') {
ny--;
} else {
ny++;
}
if (!st[nx][ny]) {
st[nx][ny] = true;
q.push({nx, ny});
}
}
}
}
if (st[2][n]) {
cout << "YES\n";
} else {
cout << "NO\n";
}
}
void prework() {
}
int main() {
cctie;
prework();
int T;
cin >> T;
while (T--) {
solve();
}
return 0;
}
D. Tandem Repeats?
枚举/动态规划。
枚举:考虑答案能否为 \(2k\),我们则要找一个子串 \(s[i...(i + k - 1)] = s[i+k...(i+2k-1)]\),构建一个新数组 \(b\),\(b[i]\) 表示 \(s[i]\) 是否等于 \(s[i + k]\),则要确定的是 \(b\) 数组中是否存在长度为 \(k\) 且和为 \(k\) 的子区间,这很容易 \(O(n)\) 解决,而 \(k\) 的取值为 \([0, {n\over2}]\),直接枚举即可。
动态规划:求后缀的最长公共前缀。
时间复杂度:\(O(n^2)\) 。
#include <bits/stdc++.h>
using namespace std;
#define cctie ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define all(x) x.begin(), x.end()
#define ALL(x) x.begin() + 1, x.end()
using i64 = long long;
void solve() {
string s;
cin >> s;
int n = s.size(), ans = 0;
for (int l = 1; l <= n / 2; l++) {
int cnt = 0;
for (int i = 0, j = 0; i + l < n; i++) {
if (s[i] == s[i + l] || s[i] == '?' || s[i + l] == '?') {
cnt++;
if (cnt == l) {
ans = l * 2;
break;
}
} else {
cnt = 0;
}
}
}
cout << ans << '\n';
}
void prework() {
}
int main() {
cctie;
prework();
int T;
cin >> T;
while (T--) {
solve();
}
return 0;
}
E. Clique Partition
贪心、构造。
考虑每一个团皆由连续的点集所构成,因为这样能使 \(|i - j|\) 最小,打表能发现点的数量小于等于 \(k\) 的团能构造,而 \(k + 1\) 的团不行,所以每 \(k\) 个点构成一个团,剩余不足 \(k\) 个的点构成一个团,构造方法为先使每个点的值为其编号即 \(a_i = i\),再在每个团的前、后半部分各自翻转。这样构造前、后半部分各自内部两点间的值显然不会超过 \(k\),而前后半部分各选一点间的值最多为 \(k\) 。
时间复杂度:\(O(n)\) 。
#include <bits/stdc++.h>
using namespace std;
#define cctie ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define all(x) x.begin(), x.end()
#define ALL(x) x.begin() + 1, x.end()
using i64 = long long;
void solve() {
int n, k;
cin >> n >> k;
int col = 0;
vector<int> a(n + 1), c(n + 1);
iota(ALL(a), 1);
for (int i = 1; i <= n; i += k) {
int j = min(i + k - 1, n), h = i + j >> 1;
reverse(a.begin() + i, a.begin() + h + 1);
reverse(a.begin() + h + 1, a.begin() + j + 1);
fill(c.begin() + i, c.begin() + j + 1, ++col);
}
for (int i = 1; i <= n; i++) {
cout << a[i] << " \n"[i == n];
}
cout << col << '\n';
for (int i = 1; i <= n; i++) {
cout << c[i] << " \n"[i == n];
}
}
void prework() {
}
int main() {
cctie;
prework();
int T;
cin >> T;
while (T--) {
solve();
}
return 0;
}
标签:Educational,cin,int,begin,long,Codeforces,using,163,define
From: https://www.cnblogs.com/xiojoy/p/18077067