做完本期以后,最近就不会再发布 AtCoder 的往届比赛了(备战蓝桥杯ing)

补题链接:Here

ABC题都是水题,这里直接跳过

D - Alter Altar

题意:一个R-W串,可以进行两种操作:1. 交换任意两个字符,2. 改变任意一个字符。问最少操作几次,可以使得串中不包含WR

思路:

可以发现,使用操作 AtCoder Beginner Contest 174 个人题解(ABC水题,D思维,E题经典二分,F离线树状数组) - 图1 总不劣于操作 AtCoder Beginner Contest 174 个人题解(ABC水题,D思维,E题经典二分,F离线树状数组) - 图2 的 。最终需要把串变为R...RW...W的形式,所以先统计R的个数 AtCoder Beginner Contest 174 个人题解(ABC水题,D思维,E题经典二分,F离线树状数组) - 图3 ,然后统计前 AtCoder Beginner Contest 174 个人题解(ABC水题,D思维,E题经典二分,F离线树状数组) - 图4 个字符中R的个数 AtCoder Beginner Contest 174 个人题解(ABC水题,D思维,E题经典二分,F离线树状数组) - 图5 ,最后的结果就是 AtCoder Beginner Contest 174 个人题解(ABC水题,D思维,E题经典二分,F离线树状数组) - 图6

  1. int main() {
  2. ios_base::sync_with_stdio(false), cin.tie(0);
  3. int n; string s;
  4. cin >> n >> s;
  5. int r = 0, rr = 0;
  6. for (int i = 0; i < s.size(); ++i)
  7. if (s[i] == 'R') r++;
  8. for (int i = 0; i < r; ++i)
  9. if (s[i] == 'R') rr++;
  10. cout << r - rr;
  11. return 0;
  12. }

E - Logs

AtCoder Beginner Contest 174 个人题解(ABC水题,D思维,E题经典二分,F离线树状数组) - 图7 根木条,每条长为 AtCoder Beginner Contest 174 个人题解(ABC水题,D思维,E题经典二分,F离线树状数组) - 图8 ,最多锯 AtCoder Beginner Contest 174 个人题解(ABC水题,D思维,E题经典二分,F离线树状数组) - 图9 次 ,问锯完后最长的木条最短有多长(结果进位为整数)。

思路:经典二分。二分查找最后的答案,判断所需要的次数是否超过 AtCoder Beginner Contest 174 个人题解(ABC水题,D思维,E题经典二分,F离线树状数组) - 图10 次。

  1. // Murabito-B 21/04/09
  2. #include <bits/stdc++.h>
  3. using namespace std;
  4. using ll = long long;
  5. int main() {
  6. ios_base::sync_with_stdio(false), cin.tie(0);
  7. int n, k;
  8. cin >> n >> k;
  9. vector<ll> a(n);
  10. for (ll &x : a) cin >> x;
  11. ll l = 1, r = *max_element(a.begin(), a.end());
  12. while (l <= r) {
  13. ll mid = l + (r - l) / 2;
  14. ll ans = 0;
  15. for (ll i : a) ans += (i - 1) / mid;
  16. if (ans > k) l = mid + 1;
  17. else
  18. r = mid - 1;
  19. }
  20. cout << l;
  21. return 0;
  22. }

F - Range Set Query

给定数组 AtCoder Beginner Contest 174 个人题解(ABC水题,D思维,E题经典二分,F离线树状数组) - 图11,进行 AtCoder Beginner Contest 174 个人题解(ABC水题,D思维,E题经典二分,F离线树状数组) - 图12次 询问,每次需要回答 AtCoder Beginner Contest 174 个人题解(ABC水题,D思维,E题经典二分,F离线树状数组) - 图13区间内不同数字的个数。

思路:

经典树状数组解法,离线做法是按查询区间右端点排序然后依次处理,过程中用树状数组记录和更新当前状态。同一个数字,只有最后一次出现是有效的。

代码学习自 CP wiki

  1. // Murabito-B 21/04/09
  2. #include <bits/stdc++.h>
  3. using namespace std;
  4. using ll = long long;
  5. // 树状数组类
  6. template <class T>
  7. class FenwickTree {
  8. int limit;
  9. vector<T> arr;
  10. T lowbit(T x) { return x & (-x); }
  11. public:
  12. FenwickTree(int limit) {
  13. this->limit = limit;
  14. arr = vector<T>(limit + 1);
  15. }
  16. void update(int idx, T val) {
  17. for (; idx <= limit; idx += lowbit(idx)) arr[idx] += val;
  18. }
  19. T query(int idx) {
  20. T ans = 0;
  21. for (; idx > 0; idx -= lowbit(idx)) ans += arr[idx];
  22. return ans;
  23. }
  24. };
  25. int main() {
  26. ios_base::sync_with_stdio(false), cin.tie(0);
  27. int n, q;
  28. cin >> n >> q;
  29. vector<int> a(n + 1);
  30. for (int i = 1; i <= n; ++i) cin >> a[i];
  31. vector<pair<int, int>> Q;
  32. for (int i = 0, l, r; i < q; ++i) {
  33. cin >> l >> r;
  34. Q.push_back({l, r});
  35. }
  36. vector<int> order(q);
  37. for (int i = 0; i < q; ++i) order[i] = i;
  38. sort(order.begin(), order.end(), [&](int i, int j) { return Q[i].second < Q[j].second; });
  39. vector<int> ans(q), pos(n + 1);
  40. int lst = 0;
  41. FenwickTree<int> ft(n);
  42. for (int i = 0; i < q; ++i) {
  43. int k = order[i];
  44. int l = Q[k].first, r = Q[k].second;
  45. for (int j = lst + 1; j <= r; ++j) {
  46. if (pos[a[j]] != 0)
  47. ft.update(pos[a[j]], -1);
  48. ft.update(j, 1);
  49. pos[a[j]] = j;
  50. }
  51. ans[k] = ft.query(r) - ft.query(l - 1);
  52. lst = r;
  53. }
  54. for (int i : ans) cout << i << "\n";
  55. return 0;
  56. }