C++の練習を兼ねて, AtCoder Beginner Contest 229 の 問題C (Cheese) ~ 問題D (Longest X) を解いてみた.
■感想.
1. 問題C, Dは, 方針を絞り込むことが出来たので, AC版に到達できたと思う.
2. 二分探索の復習が出来たので, 非常に良かったと思う.
3. 引き続き, 時間を見つけて, 過去問の学習を進めていきたいと思う.
本家のサイト AtCoder Beginner Contest 229 解説 の 各リンク を ご覧下さい.
■C++版プログラム(問題C/AC版).
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 |
// C++(GCC 9.2.1) #include <bits/stdc++.h> using namespace std; using LL = long long; using P = pair<int, int>; using vp = vector<P>; #define repex(i, a, b, c) for(int i = a; i < b; i += c) #define repx(i, a, b) repex(i, a, b, 1) #define rep(i, n) repx(i, 0, n) #define repr(i, a, b) for(int i = a; i >= b; i--) #define pb push_back #define a first #define b second #define all(x) x.begin(), x.end() int main(){ // 1. 入力情報. int N, W; scanf("%d %d", &N, &W); vp v; rep(i, N){ int a, b; scanf("%d %d", &a, &b); v.pb({a, b}); } // 2. sort. sort(all(v)); reverse(all(v)); // 3. おいしさの最大値は? LL ans = 0; for(auto &p : v){ // 使用可能な重さ. int u = min(W, p.b); // おいしさ集計. ans += (LL)p.a * (LL)u; // 重さの上限を更新. W -= u; } // 4. 出力. printf("%lld\n", ans); return 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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
[入力例] 3 5 3 1 4 2 2 3 [出力例] 15 ※AtCoderテストケースより [入力例] 4 100 6 2 1 5 3 9 8 7 [出力例] 100 ※AtCoderテストケースより [入力例] 10 3141 314944731 649 140276783 228 578012421 809 878510647 519 925326537 943 337666726 611 879137070 306 87808915 39 756059990 244 228622672 291 [出力例] 2357689932073 ※AtCoderテストケースより [入力例] 20 2020 11129 114 9830 189 6935 203 10470 183 4882 269 8083 45 10131 101 9683 142 571 174 4186 208 10556 83 6067 128 2315 200 10052 283 6805 124 7139 63 727 261 175 205 3831 205 4787 239 [出力例] 16761809 |
■C++版プログラム(問題D/AC版).
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 |
// C++(GCC 9.2.1) #include <bits/stdc++.h> using namespace std; #define repex(i, a, b, c) for(int i = a; i < b; i += c) #define repx(i, a, b) repex(i, a, b, 1) #define rep(i, n) repx(i, 0, n) #define repr(i, a, b) for(int i = a; i >= b; i--) int dCum[202020]; int main(){ // 1. 入力情報. char s[202020]; int K; scanf("%s %d", s, &K); int N = strlen(s); // 2. 累積和. rep(i, N) dCum[i + 1] = dCum[i] + (s[i] == '.'); // 3. 評価関数. auto f = [&](int m) -> bool { // 3-1. 各区間で, K個以下 の '.' が 見つかるか? bool ok = false; rep(i, N + 1 - m){ if(dCum[i + m] - dCum[i] <= K){ ok = true; break; } } // 3-2. 判定結果. return ok; }; // 4. 二分探索で確認してみる. int l = 0, h = N + 1, m; while(l + 1 < h){ int m = (h + l) >> 1; if(f(m)) l = m; else h = m; // printf("h=%d l=%d m=%d\n", h, l, m); } // 5. 出力. printf("%lld\n", l); return 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 |
[入力例] XX...X.X.X. 2 [出力例] 5 ※AtCoderテストケースより [入力例] XXXX 200000 [出力例] 4 ※AtCoderテストケースより [入力例] X..X....X.X.XXX.XX.X.XXXXXX...XXX....XX.X.X.XX..X. 3 [出力例] 15 [入力例] .XXX.XXX..X...XXX.X..XXXX.XXX.X...XXX..XXXX....X.XX.X.XXXXX.....X.XXXX....XX.XXX..XX..X....XX.X.XXXX 5 [出力例] 17 [入力例] XX....X..XXX...X...XXX.X.XX..XX.X.X...X..XX...X...XXX.XXX.....XXXX.XX.X...X.X.XX..XXXX.XXX.X..XXXXXXX.....XXXXXXXX..XX..X.....X..XX...XX..XXX.X..X....X.X.X.X..X.X..X.X.X..XX.XX..X.X...X.XX........X.X. 7 [出力例] 25 |