A. Special Characters(模拟)
#include <iostream>
using namespace std;
int main() {
int t, n;
scanf("%d", &t);
while(t--){
scanf("%d", &n);
if(n % 2 == 1) printf("NO\n");
else{
printf("YES\n");
for(int i = 1; i <= n; i+=2){
char c = 'A' + (i / 2);
printf("%c%c", c, c);
}
printf("\n");
}
}
return 0;
}
B. Array Fix(贪心)
1.数字最多两位,所以数字的拆解方案惟一
2.数字拆开一定变小,所以最后一个数不拆
3.如果拆开,代表当前数大于前一个数,此时拆开要满足几点要求:后面的个位数不大于前一个数,前面的个位数不大于后一个个位数
#include<iostream>
using namespace std;
const int N = 100;
int a[N];
int main(){
int t, n;
scanf("%d", &t);
while(t--){
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
int x = a[n], f = 1;
for(int i = n - 1; i >= 1; i--){
if(a[i] > x){
if(a[i] / 10 > a[i] % 10 || a[i] % 10 > x || a[i] < 10){
f = 0;
break;
}
x = a[i] / 10;
}else x = a[i];
}
if(f) printf("YES\n");
else printf("NO\n");
}
return 0;
}
C. Arrow Path(bfs)
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int N = 2e5 + 10;
char g[3][N];
int st[3][N];
int n;
int dx[] = {0, 0, -1, 1};
int dy[] = {-1, 1, 0, 0};
int bfs(int x, int y){
memset(st, 0, sizeof(st));
st[x][y] = 1;
queue<pair<int, int>> q;
q.push({x, y});
while(q.size()){
auto it = q.front();
q.pop();
for(int i = 0; i < 4; i++){
int a = it.first + dx[i], b = it.second + dy[i];
if(a < 1 || a > 2 || b < 1 || b > n) continue;
if(g[a][b] == '<') b--;
else if(g[a][b] == '>') b++;
if(a < 1 || a > 2 || b < 1 || b > n) continue;
if(st[a][b]) continue;
if(a == 2 && b == n) return 6;
st[a][b] = 1;
q.push({a, b});
}
}
return 0;
}
int main(){
int t;
scanf("%d", &t);
while(t--){
scanf("%d", &n);
for(int i = 1; i <= 2; i++){
for(int j = 1; j <= n; j++){
cin>>g[i][j];
}
}
int res = bfs(1, 1);
if(res == 6) printf("YES\n");
else printf("NO\n");
}
return 0;
}
D. Tandem Repeats?(双指针)
区间长度是独立的,从大到小枚举区间长度,如果找到了直接退出
#include<iostream>
#include<cstring>
using namespace std;
string s;
int check(int l, int r){
int mid = (l + r) / 2;
int i = l, j = mid + 1;
while(i <= mid && j <= r){
if(s[i] != s[j]){
if(s[i] != '?' && s[j] != '?') return 0;
}
i++, j++;
}
return 1;
}
int main(){
int t;
scanf("%d", &t);
int n;
while(t--){
cin>>s;
int n = s.size(), ans = 0;
for(int len = n; len >= 2; len--){
for(int i = 0; i + len - 1 < n; i++){
int j = i + len - 1;
if(len % 2 == 0 && check(i, j)){
ans = max(ans, len);
break;
}
}
}
printf("%d\n", ans);
}
return 0;
}
E. Clique Partition(构造)
|i - j| + |ai - aj| <= k,让下标差大的点权差小,从左到右每 k 个进行这样构造,不足 k 个就按剩下的个数进行构造
最平衡的方法是:
ai 4 3 2 1 8 7 6 5
i 1 2 3 4 5 6 7 8
#include<iostream>
#include<cstring>
using namespace std;
const int N = 50;
int a[N], c[N];
int n, k, cnt;
void dfs(int u, int id){
if(u > n){
cnt = id - 1;
return;
}
// 每 k 个构造一个群
int num = min(n - u + 1, k);
int x = u;
for(int i = u + num / 2 - 1; i >= u; i--){
a[i] = x++;
c[i] = id;
}
for(int i = u + num - 1; i >= u + num / 2; i--){
a[i] = x++;
c[i] = id;
}
dfs(u + num, id + 1);
}
int main(){
int t;
scanf("%d", &t);
while(t--){
memset(a, 0, sizeof(a));
memset(c, 0, sizeof(c));
scanf("%d%d", &n, &k);
dfs(1, 1);
for(int i = 1; i <= n; i++) printf("%d ", a[i]);
printf("\n%d\n", cnt);
for(int i = 1; i <= n; i++) printf("%d ", c[i]);
printf("\n");
}
return 0;
}