C++の練習を兼ねて, AtCoder Beginner Contest 256 の 問題C (Filling 3×3 array) ~ 問題E (Takahashi’s Anguish) を解いてみた.
■感想.
1. 問題Eは, 方針が見えなかったので, 解説を参考にして, ようやく, AC版に到達出来た.
2. 幅優先探索の復習が出来たので, 非常に良かったと思う.
3. 解説に詳しく説明されているように Functional Graph について, 知ることが出来たので, 新たな知識を蓄積できたので, 非常に良かったと思う.
4. 引き続き, 時間を見つけて, 過去問の学習を進めていきたいと思う.
本家のサイト AtCoder Beginner Contest 256 解説 の 各リンク を ご覧下さい.
■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 |
// 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 main(){ // 1. 入力情報. int h1, h2, h3, w1, w2, w3; scanf("%d %d %d %d %d %d", &h1, &h2, &h3, &w1, &w2, &w3); // 2. カウント. int ans = 0; repx(a, 1, min(h1, w1)){ repx(b, 1, min(h1, w2)){ repx(c, 1, min(h2, w1)){ repx(d, 1, min(h2, w2)){ int v13 = h1 - a - b; int v23 = h2 - c - d; int v31 = w1 - a - c; int v32 = w2 - b - d; if(v13 <= 0 || v23 <= 0 || v31 <= 0 || v32 <= 0) continue; int v331 = w3 - v13 - v23; int v332 = h3 - v31 - v32; if(v331 > 0 && v332 > 0 && v331 == v332) ++ans; } } } } // 3. 出力. printf("%d\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 |
[入力例] 3 4 6 3 3 7 [出力例] 1 ※AtCoderテストケースより [入力例] 3 4 5 6 7 8 [出力例] 0 ※AtCoderテストケースより [入力例] 5 13 10 6 13 9 [出力例] 120 ※AtCoderテストケースより [入力例] 20 25 30 22 29 24 [出力例] 30613 ※AtCoderテストケースより [入力例] 10 7 13 9 9 12 [出力例] 395 [入力例] 15 20 17 20 17 15 [出力例] 6694 [入力例] 22 23 12 19 20 18 [出力例] 7535 |
■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 |
// C++(GCC 9.2.1) #include <bits/stdc++.h> using namespace std; 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 int s[202020]; int main(){ // 1. 入力情報. int N; scanf("%d", &N); rep(i, N){ int l, r; scanf("%d %d", &l, &r); ++s[l]; --s[r]; } // 2. いもす法. rep(i, 202020 - 1) s[i + 1] += s[i]; // 3. 区間を集計. vp v; int x = 0; rep(i, 202020){ // 左端. if(!x && s[i]) x = i; // 右端. if(x && !s[i]){ v.pb({x, i}); x = 0; } } // 4. 出力. for(auto &p : v) printf("%d %d\n", p.a, p.b); 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 67 68 69 70 71 72 73 74 |
[入力例] 3 10 20 20 30 40 50 [出力例] 10 30 40 50 ※AtCoderテストケースより [入力例] 3 10 40 30 60 20 50 [出力例] 10 60 ※AtCoderテストケースより [入力例] 10 12 41 41 43 62 75 2 5 56 167 300 460 367 810 600 799 1270 1327 1034 1042 [出力例] 2 5 12 43 56 167 300 810 1034 1042 1270 1327 [入力例] 20 11 33 61 75 78 131 3 5 71 189 142 355 498 649 594 919 1281 1346 1041 1052 24 44 85 93 230 265 3035 3038 86 198 201 394 500 891 602 826 2386 2444 2415 2435 [出力例] 3 5 11 44 61 394 498 919 1041 1052 1281 1346 2386 2444 3035 3038 |
■C++版プログラム(問題E/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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
// 解き直し. // https://atcoder.jp/contests/abc256/editorial/4135 // C++(GCC 9.2.1) #include <bits/stdc++.h> using namespace std; using vi = vector<int>; using vvi = vector<vi>; 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--) #define pb push_back const LL INF = 202020202020202020; LL b[202020]; int main(){ // 1. 入力情報. int N; scanf("%d", &N); vvi G(N); vi FG(N); rep(i, N){ int x; scanf("%d", &x); --x; // 双方向のグラフ. G[i].pb(x); G[x].pb(i); // Functional Graph. FG[i] = x; } rep(i, N) scanf("%lld", &b[i]); // 2. bfs. // https://ja.wikipedia.org/wiki/幅優先探索 auto bfs = [&](vvi &G, int s, int* c, int l){ // 空のキュー. queue<int> q; // 連結成分番号を設定. c[s] = l; // 探索地点 s をキュー q に追加. q.push(s); while(!q.empty()){ // キューから取り出す. int u = q.front(); q.pop(); // 取り出した要素を処理. for(auto &e : G[u]) if(!c[e] && e != s) c[e] = l, q.push(e); } }; int c[N], idx = 0; vi v; rep(i, N) c[i] = 0; rep(i, N){ if(!c[i]){ // 連結成分の抽出. bfs(G, i, c, ++idx); // サイクルの起点となる頂点. v.pb(i); } } // 3. 集計. LL ans = 0; rep(i, v.size()){ // 3-1. サイクルの起点は? set<int> st; int cur = v[i]; while(!st.count(cur)){ st.insert(cur); cur = FG[cur]; } // 3-2. サイクルの起点から, 不満度の最小値を抽出. LL minC = INF; st.clear(); while(!st.count(cur)){ minC = min(minC, b[cur]); st.insert(cur); cur = FG[cur]; } // 3-3. 加算. ans += minC; } // 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 |
[入力例] 3 2 3 2 1 10 100 [出力例] 10 ※AtCoderテストケースより [入力例] 8 7 3 5 5 8 4 1 2 36 49 73 38 30 85 27 45 [出力例] 57 ※AtCoderテストケースより [入力例] 5 2 3 2 5 4 5 7 3 6 5 [出力例] 8 [入力例] 10 10 10 5 3 4 8 5 5 2 9 3 8 5 12 3 7 10 4 6 7 [出力例] 9 [入力例] 20 2 1 4 5 3 7 9 7 8 11 12 11 14 15 16 17 13 19 18 19 997 865 1169 1082 803 860 1262 860 980 790 984 760 657 734 731 684 769 1141 1106 1174 [出力例] 5051 |