C++の練習を兼ねて, 第八回 アルゴリズム実技検定 の 問題G (K番目の要素) を解いてみた.
■感想.
1. 問題Gは, 解説見る前に, AC版に到達出来たので, とりあえず良かったと思う.
2. 二分探索の復習が出来たので, 非常に良かったと思う.
3. 引き続き, 時間を見つけて, 過去問の学習を進めていきたいと思う.
本家のサイト 第八回 アルゴリズム実技検定 の 各リンク を ご覧下さい.
■C++版プログラム(問題G/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 50 |
// C++(GCC 9.2.1) #include <bits/stdc++.h> using namespace std; using LL = long long; #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--) LL a[101010], b[101010], c[101010]; int main(){ // 1. 入力情報. int N; LL K, l = 0, h = 0, m; scanf("%d %lld", &N, &K); rep(i, N){ scanf("%lld %lld %lld", &a[i], &b[i], &c[i]); h = max(h, b[i] + (a[i] - 1) * c[i]); } h = 2 * h + 1; // 2. 評価関数. auto f = [&](LL m) -> bool { // 2-1. 各数列 で, m以下となる個数. LL ret = 0; rep(i, N){ if(m < b[i]) continue; // 最大, a[i]個 までの 制約事項があるので, 注意. ret += min(a[i], (m - b[i]) / c[i] + 1); } // 2-2. 判定結果. return (ret < K); }; // 3. 二分探索で確認してみる. while(l + 1 < h){ LL m = (h + l) >> 1; if(f(m)) l = m; else h = m; // printf("h=%lld l=%lld m=%lld\n", h, l, m); } // 4. 出力. printf("%lld\n", h); 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 64 65 66 |
[入力例] 2 4 3 2 2 2 3 4 [出力例] 6 ※AtCoderのテストケースより [入力例] 2 10 4 1000000000 1000000000 6 1000000000 1000000000 [出力例] 6000000000 ※AtCoderのテストケースより [入力例] 5 10 3 1 4 1 5 9 2 6 5 3 5 8 9 7 9 [出力例] 16 ※AtCoderのテストケースより [入力例] 10 30 7 6 3 1 2 5 9 6 1 11 2 7 2 6 7 1 6 3 10 2 7 8 6 2 2 2 5 12 4 1 [出力例] 12 [入力例] 15 72 9 16 23 11 12 7 10 16 23 7 2 4 10 10 2 25 17 11 17 14 19 5 16 23 12 3 9 15 12 5 13 7 21 1 15 20 15 5 12 8 4 24 16 2 15 [出力例] 61 |
■参照サイト
第八回 アルゴリズム実技検定