notes

競技プログラミングで解いた問題を記録しています。

第一回 アルゴリズム実技検定

A - 2 倍チェック

解答:https://atcoder.jp/contests/past201912-open/submissions/19493518

解法:一文字目からチェックし英小文字ならerrorを出力。全て数字ならstoiして2倍する。


B - 増減管理

解答:https://atcoder.jp/contests/past201912-open/submissions/19493538

解法:前日からの増減分に応じて文字列を出力する。


C - 3 番目

解答:https://atcoder.jp/contests/past201912-open/submissions/19493555

解法:降順にソートし、a[2]を出力する。


D - 重複検査

解答:https://atcoder.jp/contests/past201912/submissions/8943992

解法:各数字が何回aに登場するかをカウントする。カウントが全て1ならば、書き換えは起きていない。そうでないならば、カウント0の数字がカウント2の数字に書き換えられている。


E - SNS のログ

解答:https://atcoder.jp/contests/past201912-open/submissions/19493617

解法:bool型の2次元配列follow[x][y]を準備する。follow[x][y] = true ⇔ xはyをフォローしている とする。
1, 2のクエリは愚直に実装する。3のクエリについて、一旦フォロー対象を別の配列に格納し、全てのフォロワーについてのチェックが終わった後にフォロー反映を行う必要がある。


F - DoubleCamelCase Sort

解答:https://atcoder.jp/contests/past201912-open/submissions/19493632

解法:まずは単語ごとに分割し、全ての単語をvectorに格納する。格納する際は全て英小文字にする。その後ソートし、最初の文字と最後の文字を大文字にして出力する。最初の格納方法に少し工夫が必要。


G - 組分け

解答:https://atcoder.jp/contests/past201912-open/submissions/19493647

解法:全ての組分けを試し、幸福度の最大値を求める。より具体的には、0, 1, 2から成る長さNの文字列を組分けと対応させ、この文字列を全て生成し、各文字列について幸福度を計算する。


H - まとめ売り

解答:https://atcoder.jp/contests/past201912-open/submissions/9963675

解法:セット販売、全種類販売では、カード数が購入数に満たないカードが一種類でもあれば販売しないのがミソ。セット販売の購入数、セット販売対象カードの最小枚数、全種類販売の購入数、全種類カードの最小枚数を記憶しておき、各クエリ時に適切に更新してゆく。


I - 部品調達

解答:https://atcoder.jp/contests/past201912-open/submissions/19493660

解法:すでに持っている部品のインデックスの集合をビット列と見なして、ビットDPを行う。具体的には、dp[i][S]:i番目のセット販売まで見たときに、持っている部品のインデックスの集合がSである場合の購入金額の最小値を表す。


J - 地ならし

解答:https://atcoder.jp/contests/past201912-open/submissions/10035553

解法:最小コストを実現する経路はあるマス(s, t)が存在して次が成り立つ。

  • 最小コストはdist[((H-1, 0), (s, t)] + dist[(s, t), (H-1, W-1)]+ dist[(s, t), (0, W-1)]
  • パス(H-1, 0)→(s, t)、(s, t)→(H-1, W-1) 、(s, t)→(0, W-1)が共通して通るマスは(s, t)のみである。

これより、全てのマス(s, t)に対して上記distを計算し、その最小値を求めればよい。ただし、(s, t)には1度入ればそれ以降のコストがかからないため、2A[s][t]を除く必要があることに注意する。


K - 巨大企業

解答:https://atcoder.jp/contests/past201912-open/submissions/19493681

解法:aとbのLCAがbであればYesを出力し、そうでなければNoを出力する。LCAはライブラリを使用した。


L - グラデーション

解答:https://atcoder.jp/contests/past201912-open/submissions/10039677

解法:小さい塔のうち連結するものをあらかじめ決めておき、大きな塔すべてと決めておいた小さい塔の最小全域木の構成コストをクラスカル法で求める。小さい塔の組み合わせを全て試せばOK。


M - おまかせ

解答:https://atcoder.jp/contests/past201912-open/submissions/10040347

解法:蟻本P.132の平均最大化の応用。

平均(1質量あたりの価値)最大化は二分探索の応用で、「C(x):平均をx以上にできるか」という条件について「 Σ(v[i] - x * w[i]) ≧ 0 」をチェックする。

この問題では通常カード5枚、通常カード4枚+お助けカード1枚のそれぞれについて「 Σ(v[i] - x * w[i]) ≧ 0」をチェックすればよい。


N - 整地

解答:https://atcoder.jp/contests/past201912-open/submissions/10067145

解法:車が通る場所を決めると、各石について取り除く必要があるかどうかが一意に決まる。石が[li, ri]にある場合、車が通る場所の左端点が(li - c, ri)となる場合にその石を取り除かなければならない。このとき石を取り除くためにはコストがpiかかるので、車が通る場所の左端点を設定して取り除く石のコストを合計すればよい。

石の合計コストが変化するのは各石についてli - c(減少)とri(増加)であるため、これらの座標とコスト増減を配列に格納し、座標の小さい方からコストを変化させてゆき、コストの最小値を求める。

コスト増減時に重要な点として、(li - c, ri)は開区間として処理する必要がある。すなわち、石が[li, ri]にある場合、車が通る場所の左端点をli - c, riにそれぞれ設定することが可能であることに注意が必要である。


O - 持久戦

解答:https://atcoder.jp/contests/past201912-open/submissions/10095653

解法:各試行で現れるサイコロの目を数列にすると、狭義単調増加になる。 特に、全てのサイコロの中で最も大きい目を出すと、その時点で操作終了となる。

サイコロを区別せずに、xをサイコロの目としたときdp[x]を「そのサイコロの目が出た後にサイコロが何回振れるか」という値とする。このとき dp[x]の値はy>xなるyについてのdp[y]が分かれば算出できる。