活動日誌'19 No.005

投稿者 NOSS | 2019-05-10

こんにちは、NOSSです。今日はC++講習会第2回目とバーチャルコンテストを行いました。

C++講習会

APG4bの「1.08.変数のスコープ」から「1.12.文字列と文字」までと配列について説明を行いました。

C++の基本についてはほぼ完了したので後はAtCoder Problemsで問題を解いていくと強くなれると思います。

入部関係の話

現部員含めて今年度の部員名簿に記名してもらいました。5月中の活動で受け付けています。

5月18日(土)に新歓食事会を予定しています。参加したい方はTwitterのDMなどでも連絡をください。期限は5/13(月)までです。

コンテストの解説

コンテストのリンクはこちら


ABC008 A - アルバム

https://atcoder.jp/contests/abc008/tasks/abc008_1

TS+1T-S+1 が答えです。


ARC002 A - うるう年

https://atcoder.jp/contests/arc002/tasks/arc002_1

if文で場合分けをします。コード例を参考にして下さい。

解法コード例


ABC006 A - Shiritori

https://atcoder.jp/contests/abc060/tasks/abc060_a

文字列 SS の先頭は S[0]S[0]、末尾は S[S.size()1]S[S.size()-1] でアクセスできます。

解法コード例


ABC115 B - Christmas Eve Eve

https://atcoder.jp/contests/abc115/tasks/abc115_b

もっとも値段の高い品物を半額にしてもらうのが最適なので答えは pipmax/2\sum p_i - p_{max} / 2 となります。


ABC073 C - Sentou

https://atcoder.jp/contests/arc073/tasks/arc073_a

ii 人目がスイッチを押してから、 i+1i+1 人目が来るまでのことを考えてみます。

  • ti+1tiTt_{i+1} - t_i \le T のとき
    この間、お湯は流れ続けます。

  • ti+1ti>Tt_{i+1} - t_i \gt T のとき
    TT 秒間お湯が流れてから止まります。

以上より、ii 人目と i+1i+1 人目の間のお湯が流れる時間がわかりました。

よって、各人について次の人が来るまでの時間を求め、min(T,ti+1ti)\min(T, t_{i+1} - t_i) の総和を求めれば答えとなります。
NN 人目の後には誰も来ないことに注意してください。

解法コード例


ABC078 D - ABS

https://atcoder.jp/contests/abc078/tasks/arc085_b

まず、N=1N=1 のとき答えは a1W|a_1 - W| です。

N2N \ge 2 のときを考えます。先手は初手で NN 枚すべて取ることによって aNW|a_N - W| にすることができます。
また、初手で N1N-1 枚取ることによって aN1aN|a_{N-1} - a_N| にすることができます。

初手で kk 枚取ったときを考えます(1kN21 \le k \le N-2)。 このとき後手は N1N-1 枚目を取ることによっていつでもスコアを aN1aN|a_{N-1} - a_N| にすることができます。 つまり、今後スコアが大きくなってしまうパターンがあったとしても N1N-1 枚目をとれば aN1aN|a_{N-1} - a_N| にできるのでスコアは少なくとも aN1aN|a_{N-1} - a_N| 以下にすることができます。

先手の手番についても同様に、スコアが aN1aN|a_{N-1} - a_N| より小さくなってしまうパターンがあるならば N1N-1 枚目をとって aN1aN|a_{N-1} - a_N| にすればいいので、少なくとも aN1aN|a_{N-1} - a_N| 以上にすることができます。

よって、互いに最善を尽くすとスコアは aN1aN|a_{N-1} - a_N| になることが分かります。

以上より、N2N \ge 2 のときゲームの結果は aNW|a_N - W|aN1aN|a_{N-1} - a_N|22 パターンしかないことが分かるので、max(aNW,aN1aN)\max(|a_N - W|, |a_{N-1} - a_N|) が答えになります。

解法コード例


ARC021 C - 増築王高橋君

https://atcoder.jp/contests/arc021/tasks/arc021_3

部分点解法

毎回 NN 個の建物のうちコストが最小の建物を増築するのが最適です。
よって、KK 回のうち各回 NN 個の建物を愚直に調べれば O(NK)O(NK)、優先度付きキューを使えば O(KlogN)O(K \log N) で答えが求まります。

満点解法

K108K \le 10^{8} のため各回調べる方法はTLEになります。

ここで、増築がコストが小さい順に行われていくことに注目します。 KK 回目の増築にかかったコストを XX と置くと、ii 回目(1iK1 \le i \le K) の増築コストは XX 以下であることが分かります。

すなわち、各建物について増築コストが XX 以下である間は増築を続けていいことが分かります。
よって、ある XX を決め打つと各建物の増築可能な回数が求められます。NN 個の建物の増築可能回数の総和が KK 以上であれば、コスト XX 以下で KK 回の増築が行えることが分かります。

以上より、可能な XX の最小値を二分探索することで答えを得ることができます。

XX を求めたら
(X)+X×(K(X))(X未満のコストの総和) + X \times (K - (X未満でできる増築回数))
を計算すればよいです。

計算量は O(NlogXmax)O(N \log X_{max}) となります。

解法コード例


ARC028 C - 高橋王国の分割統治

https://atcoder.jp/contests/arc028/tasks/arc028_3

適当な根付き木を考えます。まず、葉は N1N-1 であることが分かります。 次に 11 つ親の頂点をみると ii個目の子の部分木を大きさを sis_i と置いて max(max(si),N1si)\max( \max(s_i), N-1-\sum s_i) が答えであると分かります。

以上より、再帰的に答えを求めることができます。

計算量は O(N)O(N) です。


ARC026 C - 蛍光灯

https://atcoder.jp/contests/arc026/tasks/arc026_3

DPで解を得ることができます。遷移に工夫が必要です。

dp[i]=dp[i] = ちょうど ii メートル以内を照らすために必要な最小コスト

と置きます。遷移は

dp[r[i]]=min(dp[r[i]],minl[i]jL(dp[j]+c[i])) dp[r[i]] = \min \left(dp[r[i]], \min_{l[i] \le j \le L} (dp[j] + c[i]) \right)

となります。蛍光灯は l[i]l[i] が小さい順に調べます。

区間の最小値の取得にセグメント木を使用すれば O(NlogL)O(N \log L) 優先度付きキューなら O(NlogN)O(N \log N) で求められます。

解法コード例(優先度付きキュー)

あるいは以下のような有向グラフの最短経路問題としても解けます。