中间两题罚时太多了。
比赛链接:https://codeforces.com/contest/1792
A. GamingForces
题解
贪心,将 1 都用第一种操作删除,其他数都用第二种操作。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #include <bits/stdc++.h> using namespace std;
int main() { ios::sync_with_stdio(false); cin.tie(nullptr);
int t; cin >> t;
while (t--) { int n; cin >> n;
int one = 0, other = 0; for (int i = 0; i < n; i++) { int x; cin >> x; (x == 1 ? one : other) += 1; } cout << (one + 1) / 2 + other << "\n"; }
return 0; }
|
题解
执行第 2 或第 3 种操作总和不变,所以可以先执行第 1 种操作,然后重复执行第 2、3 种操作,直至一种为 0,然后讨论最小情绪值和余下两种操作的大小关系就可以了。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| #include <bits/stdc++.h> using namespace std;
int main() { ios::sync_with_stdio(false); cin.tie(nullptr);
int t; cin >> t;
while (t--) { int a, b, c, d; cin >> a >> b >> c >> d;
int ans = 0, min_mood = 0; ans += a; min_mood += a; auto op = [](int& x, int& y) { int mi = min(x, y); x -= mi, y-= mi; return mi; };
if (min_mood > 0) { if (b > c) { swap(b, c); } ans += 2 * op(b, c); }
ans += op(min_mood, c);
ans += op(min_mood, d);
cout << ans + (max({b, c, d}) > 0) << "\n"; }
return 0; }
|
C. Min Max Sort
题解
操作次数最多为 ⌊2n⌋ ,从中间值找有多少数对的相对位置满足排序后的关系,从总操作次数中减去这些可以省下的操作次数即可。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| #include <bits/stdc++.h> using namespace std;
int main() { ios::sync_with_stdio(false); cin.tie(nullptr);
int t; cin >> t;
while (t--) { int n; cin >> n;
vector<int> a(n), pos(n + 1); for (int i = 0; i < n; i++) { cin >> a[i]; pos[a[i]] = i; }
int ans = n / 2;
int l, r; int val_l, val_r; if (n & 1) { l = r = find(a.begin(), a.end(), (n + 1) / 2) - a.begin(); val_l = (n + 1) / 2 - 1, val_r = (n + 1) / 2 + 1; } else { l = find(a.begin(), a.end(), n / 2) - a.begin(); r = find(a.begin(), a.end(), n / 2 + 1) - a.begin(); val_l = n / 2 - 1, val_r = n / 2 + 2; }
if (l <= r) { ans -= (n % 2 == 0); while (pos[val_l] < l and pos[val_r] > r) { l = pos[val_l], r = pos[val_r]; val_l -= 1, val_r += 1; ans -= 1; } }
cout << ans << "\n"; }
return 0; }
|
D. Fixed Prefix Permutations
题解
将值的不连续分布转化为位置的连续分布后进行二分。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| #include <bits/stdc++.h> using namespace std;
int main() { ios::sync_with_stdio(false); cin.tie(nullptr);
int t; cin >> t;
while (t--) { int n, m; cin >> n >> m;
vector a(n, vector<int>(m)), pos(a); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { cin >> a[i][j]; --a[i][j]; pos[i][a[i][j]] = j; } }
sort(pos.begin(), pos.end());
for (int i = 0; i < n; i++) { int l = 0, r = m; auto ok = [&](int mid) { vector<int> need(m, -1); for (int j = 0; j < mid; j++) { need[j] = a[i][j]; } auto it = lower_bound(pos.begin(), pos.end(), need); if (it == pos.end()) { return false; } for (int j = 0; j < mid; j++) { if (need[j] != (*it)[j]) { return false; } } return true; }; while (l < r) { int mid = (l + r + 1) / 2; if (ok(mid)) { l = mid; } else { r = mid - 1; } } cout << l << " \n"[i == n - 1]; } }
return 0; }
|