AtCoder Beginner Contest 337
B - Extended ABC
难度: ⭐
题目大意
验证给定的字符串是不是ABC扩展串, 空串也算;
解题思路
题目很简单, 没必要像我这么写, 我这是突然想到了就写了; 正常写打暴力就行, 先找A, 若没有就找B, 以此类推;
神秘代码
#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353;
typedef pair<int, int> PII;
int n, m, res;
signed main() {
IOS;
string s;
cin >> s;
string str = s.substr(0, 1);
for(int i = 1; i < s.size(); i++){
if(s[i] > 'C' || s[i] < 'A'){
cout << "No";
return 0;
}
if(s[i] != s[i - 1]) str += s[i];
}
if(str.size() > 3){
cout << "No";
return 0;
}
for(int i = 1; i < str.size(); i++){
if(str[i] < str[i - 1]){
cout << "No";
return 0;
}
}
cout << "Yes";
return 0;
}
C - Lining Up 2
难度: ⭐
题目大意
题目给了n个人跟在谁后面, 如果是-1就是第一个; 求排队的顺序;
解题思路
一道很板的链表题, 没什么好说的;
神秘代码
#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353;
typedef pair<int, int> PII;
int n, m, res;
map<int, int> mp;
signed main() {
IOS;
cin >> n;
for(int i = 1; i <= n; i++){
int a;
cin >> a;
if(a == -1) m = i;
else mp[a] = i;
}
while(m){
cout << m << ' ';
m = mp[m];
}
return 0;
}
D - Cheating Gomoku Narabe
难度: ⭐⭐⭐
题目大意
给定一个由'o' '.' 'x'组成的二维字符矩阵, 问是否可以找到一个长度为k且水平或者竖直的字符串, 该字符串由'o'和'.'组成, 找到所有满足条件的字符串中'.'最少的为多少;
解题思路
这题我没想太多, 第一想法就是用滑动窗口来做, 这样代码可能有点啰嗦, 但也没去想更巧妙的; 我们把行和列分开处理, 处理思路都是一样的, 区别只是遍历方式不一样, 因为数据范围的原因需要用一维数组来存二维矩阵; 对于一行, 我们可以用一个长度为k的窗口从头滑到尾, 合法窗口的内部不能有'x'; 我们记录每个窗口内部' . '的数量; 每得到一个合法窗口就更新一下最小值即可;
神秘代码
#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353;
typedef pair<int, int> PII;
int n, m, res;
int p[N];
int dp1[N], dp2[N];
signed main() {
IOS;
cin >> n;
for(int i = 1; i <= n; i++) cin >> p[i];
for(int i = 1; i <= n; i++){
if(p[i] > dp1[i - 1]){
dp1[i] = dp1[i - 1] + 1;
}
else dp1[i] = p[i];
}
for(int i = n; i >= 1; i--){
if(p[i] > dp2[i + 1]){
dp2[i] = dp2[i + 1] + 1;
}
else dp2[i] = p[i];
}
for(int i = 1; i <= n; i++){
res = max(res, min(dp1[i], dp2[i]));
}
cout << res;
return 0;
}
E - Bad Juice
难度: ⭐⭐⭐
题目大意
小莫有(1 ~ n)n瓶汽水, 其中有一个是坏的; 小莫找了m个朋友, 并且分给人每个人若干瓶饮料喝, 一瓶饮料可以分给多个人; 喝到坏饮料的人会拉肚子, 题目会给出每个人的情况, 1表示拉肚子, 0表示没事; 根据该情况确定哪瓶是坏掉的;
解题思路
一道非常经典的交互题, 暑假做过类似的题; 本题用二进制进行求解; 设坏掉的饮料编号为x; x的二进制表示有m位, 那么我们就可以安排m位朋友, 第i位朋友分配1 ~ n中所有二进制第(i - 1)位上是1的编号饮料; 如果x的二进制中第0, 2, 3位上是1, 那么第1, 3, 4位朋友就会拉肚子, 此时我们就会发现, 交互给的字符串其实就是x反过来的二进制表示; 这样我们就得到了x;
但是这题还有个坑点, 他要求输出最少拜托的朋友数m, 本题其实可能不用m位朋友, 而是(x - 1)的二进制位数; 因为当x的2y时, 那么第m位朋友就只会分到一瓶饮料, 即x;
所以此时我们只给m - 1位朋友即可, 如果最后得到的字符串全是0, 则说明x就是坏掉的饮料, 最后特判一下就行;
神秘代码
#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
//#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353;
typedef pair<int, int> PII;
int n, m, res;
int p[N];
int get(int x){
int num = 0;
while(x){
num++;
x >>= 1;
}
return num;
}
signed main() {
IOS;
cin >> n;
m = get(n - 1);
cout << m << endl;
for(int i = 0; i < m; i++){
vector<int> v;
for(int j = 1; j <= n; j++){
if(j >> i & 1) v.push_back(j);
}
cout << v.size() << ' ';
for(int j = 0; j < v.size(); j++){
cout << v[j] << ' ';
}
cout << endl;
}
string s;
cin >> s;
for(int i = 0; i < s.size(); i++){
if(s[i] == '1'){
res += (1 << i);
}
}
if(!res) res = n;
cout << res << endl;
return 0;
}