Codeforces Round #744 (Div. 3)
A. Casimir's String Solitaire
题目大意:给你一组只有A,B,C组成的字符串,按照如下的规则进行删除操作:每一次只能删除字母A和字母B,或者删除字母B和字母C,判断一个字符串能否被删除为空字符。
大致思路:扫描一边字符串统计出字母A,字母B,字母C的个数,如果字母A的个数加上字母B的个数等于字母C的个数该字符串即可删除为空。
代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
cin.tie(0);
int t;
cin >> t;
while (t--) {
string str;
cin >> str;
int cnta = 0, cntb = 0, cntc = 0;
for (auto s : str) {
if (s == 'A') cnta++;
if (s == 'B') cntb++;
if (s == 'C') cntc++;
}
if (cnta + cntc == cntb) {
cout << "YES" << endl;
continue;
}
cout << "NO" << endl;
}
return 0;
}
B. Shifting Sort
题目大意:给你一个长度为n无序且数字不重复的数字,按照如下方式来操作数组:在数组中选择区间$$a[l...r]$$ 的数字,将该区间的数字想左旋转d个长度。经过最多n次旋转将数组旋转成为单调递增的数组,输出每一次选择的区间和旋转的长度。
大致思路:遍历数组中的每一个数字$$a[i]$$,然后找出该数字后面比这个数字小的最小的数字$$a[p]$$, 然后选择区间$$a[i...n]$$向左旋转 $$p - i$$个长度将数字$$a[p]$$旋转到$$a[i]$$的位置。因为每一次查找的是比数字$$a[i]$$最小的数字,所以我们可以保证在n次内就可以将数组排成升序。
代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; ++i) cin >> a[i];
vector<tuple<int, int, int>> ans;
for (int i = 0; i < n; ++i) {
int tmp = a[i];
for (int j = i + 1; j < n; ++j) tmp = min(tmp, a[j]);
int pos = -1;
for (int k = i; k < n; ++k) {
if (tmp == a[k]) {
pos = k;
}
}
if (pos > i) {
ans.push_back(make_tuple(i, n, pos - i));
rotate(a.begin() + i, a.begin() + pos, a.end());
}
}
cout << ans.size() << endl;
for (int i = 0; i < ans.size(); ++i) {
int l = get<0>(ans[i]) + 1;
int r = get<1>(ans[i]);
int d = get<2>(ans[i]);
cout << l << " " << r << " " << d << endl;
}
}
return 0;
}
C.Ticks
题目大意:给你一个n * m的网格,以网格$$(i, j)$$ 为中心,向左上角45度和右上角45度画直线,其中一个单元格的对角线的长度为一个单位,所画直线的单元格被标记,问你能够用长度至少为k的线将所有单元格都标记。
大致思路:因为题目要求的是由下到上开始画像,所以我们从下有上开始遍历所有还没有被染色的单元格$$(i,j)$$,以单元格$$(i,j)$$为中心查找左上角45度和右上角45度方位为“*”的最近的单元格。 然后判断所需直线的长度是否大于k
代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int n, m, k;
cin >> n >> m >> k;
vector<vector<int>> maze(n, vector<int>(m, 1));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
char ch;
cin >> ch;
if (ch == '*') maze[i][j] = 0;
}
}
for (int i = n - 1; i >= 0; --i) {
for (int j = 0; j < m; ++j) {
if (maze[i][j] == 1) continue;
int len = 0;
while (i - len > 0 && j + len + 1 < m && j - len > 0) {
if (maze[i - len - 1][j + len + 1] == 1 ||
maze[i - len - 1][j - len - 1] == 1)
break;
++len;
}
if (len >= k) {
for (int d = 0; d <= len; ++d) {
//被染色的点修改为另一个数字,防止下次判断的时候判断错误
maze[i - d][j + d] = 2;
maze[i - d][j - d] = 2;
}
}
}
}
bool flag = true;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (maze[i][j] == 0) {
flag = false;
}
}
}
if (flag)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
return 0;
}
D.Productive Meeting
题目大意:一组人去开会,为个人都有一个开会时间,开一次会会消耗一个单位时间,让尽可能多的开会输出每一次开会人的序号。
大致思路:尽可能多的开会,就安排开会时间少的人先在一起开会,利用优先队列处理即可。
代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<int> a(n + 1);
for (int i = 1; i <= n; ++i) {
cin >> a[i];
}
priority_queue<pair<int, int>> pq;
for (int i = 1; i <= n; ++i) {
if (a[i] != 0) {
//推入第i个人的社交值和编号
pq.push(make_pair(a[i], i));
}
}
vector<pair<int, int>> ans;
while (pq.size() >= 2) {
//优先让社交值小的两个人先交流这样可以让尽可能多的人交流
int s1 = pq.top().first;
int id1 = pq.top().second;
pq.pop();
int s2 = pq.top().first;
int id2 = pq.top().second;
pq.pop();
ans.push_back(make_pair(id1, id2));
if (s1 > 1) pq.push(make_pair(s1 - 1, id1));
if (s2 > 1) pq.push(make_pair(s2 - 1, id2));
}
cout << ans.size() << endl;
for (int i = 0; i < ans.size(); ++i) {
cout << ans[i].first << " " << ans[i].second << endl;
}
}
return 0;
}
E.Permutation Minimization by Deque
题目大意:给你一个数组,让你把这个数组按照如下规则重新排序:把小的数字尽可能放前面,大的数字尽可能放后面。
大致思路:用两个数字模拟即可,一个数组放小的数据,一个放大的。
代码:
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 10;
int a[MAXN], b[MAXN], c[MAXN];
int main() {
int t;
scanf("%d", &t);
while (t--) {
int n;
scanf("%d", &n);
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
memset(c, 0, sizeof(c));
for (int i = 0; i < n; ++i) scanf("%d", &a[i]);
int cnt1 = n, cnt2 = 0;
b[cnt1] = a[0];
for (int i = 1; i < n; ++i) {
if (a[i] > b[cnt1])
c[cnt2++] = a[i];
else
b[--cnt1] = a[i];
}
for (int i = cnt1; i <= n; ++i) printf("%d ", b[i]);
for (int i = 0; i < cnt2; ++i) printf("%d ", c[i]);
printf("\n");
}
return 0;
}