Codeforces Round #712 (Div. 2) A,B,C,D,E
作者:互联网
Codeforces Round #712 (Div. 2) A,B,C,D,E
A - Déjà Vu
题意
给你一个字符串,要你往里面插入一个字符‘a’,让最终的字符串不是回文字符串。
思路
如果字符串是全a就不行,其他情况都行,从头遍历,判断第 n − i − 1 n - i - 1 n−i−1 个字符是不是 a a a ,不是的话就在第 i i i 个字符前插入 a a a 。这样一定能使第 i i i 位不对称。
比赛的时候想复杂了,还判断了回文,并且因为以为只要全部是同一个字符就不行,因此wa了一次。还好很快发现了问题。
代码
赛后写的代码
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> P;
string str;
int n;
bool isS()
{
if(str[0] != 'a')
return 0;
for(int i = 0; i < n - 1; i++)
{
if(str[i] != str[i + 1])
return 0;
}
return 1;
}
int main()
{
int T;
cin >> T;
while(T--)
{
cin >> str;
n = str.length();
if(isS())
{
cout << "NO" << endl;
continue;
}
cout << "YES" << endl;
bool flag = 0;
for(int i = 0; i < n; i++)
{
if(str[n - i - 1] != 'a' && !flag)
{
cout << 'a' << str[i];
flag = 1;
}
else
cout << str[i];
}
cout << endl;
}
return 0;
}
比赛时写的代码
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> P;
string str;
int n;
int notP()
{
for(int i = 0; i < n; i++)
{
if(str[i] != str[n - i - 1])
return i;
}
return -1;
}
bool isS()
{
if(str[0] != 'a')
return 0;
for(int i = 0; i < n - 1; i++)
{
if(str[i] != str[i + 1])
return 0;
}
return 1;
}
int main(){
int T;
cin >> T;
while(T--)
{
cin >> str;
n = str.length();
int pos = notP();
if(pos != -1)
{
bool flag = 0;
cout << "YES" << endl;
for(int i = 0; i < n; i++)
{
if(str[n - i - 1] != 'a' && !flag)
{
cout << 'a' << str[i];
flag = 1;
}
else
cout << str[i];
}
cout << endl;
}
else
{
if(isS())
cout << "NO" << endl;
else
{
cout << "YES" << endl;
cout << 'a' << str << endl;
}
}
}
return 0;
}
B - Flip the Bits
题意
给定两个01串,要求你将第一个串进行操作,每次只能选取该串0和1个数相同的前缀部分取反,判断能否翻转成第二个串。
思路
从尾向前遍历,遇到不同的,如果前缀的01个数相同就翻一下,不同就无解。01的个数以及取反都可以预处理。
犯了很不该犯的细节错误,没初始化以及遍历起点写错,白WA了一发。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wtge5ynN-1618328912190)(C:\Users\29039\AppData\Roaming\Typora\typora-user-images\image-20210413200028355.png)]
代码
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> P;
const int N = 3e5 + 10;
char str[N];
int arr[N];
int rev[N];
int ans[N];
int num[2][N];
int main(){
int T;
cin >> T;
while(T--)
{
int n;
cin >> n;
cin >> str;
num[0][0] = num[1][0] = 0;
for(int i = 1; i <= n; i++)
{
arr[i] = str[i - 1] == '0' ? 0 : 1;
rev[i] = str[i - 1] == '0' ? 1 : 0;
num[0][i] = str[i - 1] == '0' ? num[0][i - 1] + 1 : num[0][i - 1];
num[1][i] = str[i - 1] == '1' ? num[1][i - 1] + 1 : num[1][i - 1];
}
cin >> str;
for(int i = 1; i <= n; i++)
{
ans[i] = str[i - 1] == '0' ? 0 : 1;
}
bool flag = 0;
bool f = 0;
for(int i = n; i > 0; i--)
{
if(f)
{
if(rev[i] != ans[i])
{
if(num[0][i] != num[1][i])
{
flag = 1;
break;
}
f = 0;
}
}
else
{
if(arr[i] != ans[i])
{
if(num[0][i] != num[1][i])
{
flag = 1;
break;
}
f = 1;
}
}
}
if(flag)
cout << "NO" << endl;
else
cout << "YES" << endl;
}
return 0;
}
C - Balance the Bits
题意
给你一个长度为 n n n 的01串,要求你根据这个串构造两个由 ‘ ( ’ 和 ‘ ) ’ 构成长度为 n n n 的字符串,满足两个字符串都是平衡的字符串,并且在1的位置字符相同,0的位置字符不同。其中对于平衡的定义是:该字符串可以通过往括号间插入 + 和 1 使之成为一个合法的数学表达式。
思路
其实意思就是括号一一对应,每个左括号都能找到自己的右括号。
-
首先是无解的情况,当0的数量为奇数时无解,当字符串的首尾为0时无解。
-
对于有解的情况,我们把0和1的位置分开存储放在两个vector里。
- 对于所有的0,找临近的那个0组对形成一对括号,答案串1是‘()’,答案串2是‘)(’,因为0不能出现在边界所以这两种情况都是有解的;
- 对于所有的1,找最远的那个1组成一对括号,两个答案串都是‘()’。
1不能找临近的,如果找临近的样例都过不去,虽然我不能证明为什么找最远的就没问题……而且很多代码好像都是用奇偶来处理括号配对,我的思路好像有点清奇……
代码
#include <bits/stdc++.h>
#define pb push_back
using namespace std;
typedef pair<int, int> P;
const int N = 3e5 + 10;
char str[N];
char ans1[N];
char ans2[N];
int n;
vector<int> zero;
vector<int> one;
bool ok()
{
if(n % 2)
return 0;
zero.clear();
one.clear();
for(int i = 0; i < n; i++)
{
if(str[i] == '0')
{
if(i == 0 || i == n - 1)
return 0;
zero.pb(i);
}
else
one.pb(i);
}
if(zero.size() % 2)
return 0;
for(int i = 0; i < zero.size(); i += 2)
{
ans1[zero[i]] = '(';
ans1[zero[i + 1]] = ')';
ans2[zero[i]] = ')';
ans2[zero[i + 1]] = '(';
}
int m = one.size();
for(int i = 0; i < m / 2; i++)
{
ans1[one[i]] = '(';
ans1[one[m - i - 1]] = ')';
ans2[one[i]] = '(';
ans2[one[m - i - 1]] = ')';
}
return 1;
}
int main()
{
int T;
cin >> T;
while(T--)
{
cin >> n;
cin >> str;
fill(ans1, ans1 + n + 1, 0);
fill(ans2, ans2 + n + 1, 0);
if(!ok())
{
cout << "NO" << endl;
continue;
}
cout << "YES" << endl;
cout << ans1 << endl;
cout << ans2 << endl;
}
return 0;
}
D - 3-Coloring
题意
给定 n × n n \times n n×n 的棋盘,只能用三种颜色填充它,每次填充机器会限制其中一种颜色不能使用,要求你在这样的限制下填满棋盘,并且保证没有两个相邻块的颜色相同。
思路
像这样填充:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XPmPIJfu-1618328912193)(file:///C:\Users\29039\Desktop\package\qq\791515215\Image\Group2\TX\1J\TX1J4R3_D3{EEYQ`KJP9FJS.png)]
如果1已经填满了图中的位置,机器依然限制接下来的部分不许填2,就在放2的位置填3,反之亦然;因为只有1或2已经放满才会出现这样的情况,所以不可能出现相邻。
其实比赛的时候思路很对,但是不自信否定了这个思路,觉得有可能是有无解的情况的(加上vp时间有点不太好,饭点,饿死了 ≧ ﹏ ≦ 就打了一个小时就去吃饭了)。赛后补题发现思路很对,而且真的不难,有点小可惜。我还是会有自己肯定不会做D题的思维定势…
代码
#include <bits/stdc++.h>
#define pb push_back
using namespace std;
typedef pair<int, int> P;
const int N = 3e5 + 10;
queue<P> que1;
queue<P> que2;
int main()
{
int n;
cin >> n;
int num;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
if((i + j) % 2)
{
que1.push(P(i, j));
}
else
{
que2.push(P(i, j));
}
}
}
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
cin >> num;
if(num == 2)
{
if(que1.empty())
{
cout << "3 " << que2.front().first << ' ' <<
que2.front().second << endl;
que2.pop();
}
else
{
cout << "1 " << que1.front().first << ' ' <<
que1.front().second << endl;
que1.pop();
}
}
else if(num == 1)
{
if(que2.empty())
{
cout << "3 " << que1.front().first << ' ' <<
que1.front().second << endl;
que1.pop();
}
else
{
cout << "2 " << que2.front().first << ' ' <<
que2.front().second << endl;
que2.pop();
}
}
else
{
if(que1.empty())
{
cout << "2 " << que2.front().first << ' ' <<
que2.front().second << endl;
que2.pop();
}
else
{
cout << "1 " << que1.front().first << ' ' <<
que1.front().second << endl;
que1.pop();
}
}
}
}
return 0;
}
E - Travelling Salesman Problem
题意
n n n 个点,每个城市有权值 a i a_i ai、 c i c_i ci ,从城市 i i i 到城市 j j j 要花费 m a x ( a j − a i , c i ) max(a_j - a_i, c_i) max(aj−ai,ci)。
求经过所有城市并回来的最小花费。
思路
参考:Codeforces Round #712 (Div. 2)E. Travelling Salesman Problem(大思维)
代码
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> P;
const int N = 1e5 + 10;
typedef long long ll;
struct node
{
ll a, c;
bool operator < (const node& obj)
{
return a < obj.a;
}
} arr[N];
int main()
{
int n;
cin >> n;
ll ans = 0;
for(int i = 0; i < n; i++)
{
cin >> arr[i].a >> arr[i].c;
ans += arr[i].c;
}
sort(arr, arr + n);
ll maxx = arr[0].a + arr[0].c;
for(int i = 1; i < n; i++)
{
ans += max(0ll, arr[i].a - maxx);
maxx = max(maxx, arr[i].a + arr[i].c);
}
cout << ans << endl;
return 0;
}
总结
好久没有打,感觉实现上有点生疏,很多细节考虑不到。不过好在结果还不错,只是只做到C就开始摸了,D题其实思路最开始就全对但是因为不自信以及心理上摸了所以赛后才写。总之就是还需要多练,以及要自信!
多多包涵,共同进步
标签:arr,cout,cin,int,Codeforces,712,num,str,Div 来源: https://blog.csdn.net/qq_49451105/article/details/115682566