Codeforces Round #744 (Div. 3)
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;
}