ABC174に出たので、考えたことを整理してみる。
スポンサードリンク
こんにちは。ふぁんたです。
2020年8月2日のABC174に参加しました。
どういうふうに考えて、どういった実装をしたのか、
自分の頭の中の整理を兼ねて、書き出してみようと思います。
C - Repsept
C-Repsept
問題概要
Kが与えられます。
7,77,777,7777,77777 と7が増えていく数列について、Kの倍数が初めて出てくるのはいつですか?
制約として、\\(K \\leq 2 \\times 10^6\\)
考えたこと
・愚直にやってしまうと、すぐにオーバーフローしてしまいそう
→999983の入力例があり、7が90万個続く数字は流石によくないので。
・数列の実装方法は、「前のやつに10かけて7足す」をやればできそう。
・ある数字Aに10かけて7足した数をKで割ったあまりは、
AをKで割ったあまりに10かけて7足すのと同じ。
→ なら、7を増やす操作をするたびにKで割った余りを取るようにすれば、捜査する数字がKより大きくなることはない
ということに気づけば、実装ができる。
D - Alter Altar
D - Alter Altar
問題概要
RとWからなる文字列があります。
・RをWにする操作
・WをRにする操作
・好きな文字2つを入れ替える操作
ができます。
「Wの右にRがある」という状態を避ける文字列にするために、最低何回の操作が必要ですか?
\\(2 \\leq N \\leq 2 \\times 10^5\\)
考えたこと
1.全部Wにすればいい。
2.全部Rにしてもいい。
…このどちらかで、手数が少ない方では?
→という思いを打ち壊してくれたのが、入力例3です。
8
WRWWRWRR
Wは4つ、Rも4つなのに、出力は3。
「入れ替えを上手いこと使えば、全部いっしょの文字にしなくてもいいよ」
ということを言いたいがための入力例なんだと思います。
そこで、左側にR、右側にWを集めてしまえば、「WR」という文字列はなくなるので、
そうなるようにシミュレートすると、この入力例では3になりました。
なので、
1.右からRを探す。左から探している探索範囲に踏み込むか、探索範囲が文字列を超えたら終了。
2.左からWを探す。右から探している探索範囲に踏み込むか、探索範囲が文字列を超えたら終了。
3.両方見つかったら必要な操作数を1足して、その内側から探索をする(1に戻る)
をすればよいな、とわかりました。
ちなみに、Alter Altarという問題名ですが、
Alter…変える者
Altar…祭壇
という意味です。祭壇に供えられた石の色を変えるからですね。
E - logs
E - logs
問題概要
N本の丸太があります。K回まで切ることができ、その丸太たちの中で最も長いやつの長さを最小にしたいです。
最小で長さはいくつになりますか?
\\(丸太の本数 \\leq 2 \\times 10^5\\)
\\(切れる回数 \\leq 10^9\\)
\\(初期状態の各丸太の長さ \\leq? 10^9\\)
考えたこと
(間違った判断をしました。)
・切るべき丸太は最も長いやつで確定。
・それを半分にするという操作をしていけば、最小の長さは求まる。
・使うべきはPriority Queueで、実際にシミュレートして答えを出せば良い。
→ 切れる回数Kは\\(10^9\\)まであるので、絶対に間に合わない。
→ また、半分にするのが最適というわけでもない。その反例は入力例1である。
(ここから正しい判断でした)
・「最大」の丸太を「最小」化する問題 なので、二分探索を使うだろう。
→「全ての丸太の長さをX以下にすることは、カットK回以内でできるか?」という関数で二分探索を行えば良い。
・探索範囲が十分小さくなれば探索を打ち切る。
ただし、「4.9999にはできないけど、5.000001にはできるよ!」といったような場合、愚直にCeilingしてしまうと6を出力する。
→これを避けるため、出力予定の値をFloorした値を突っ込んで、達成できるかどうかを見る。
(この時彼は知る由もなかった この実装が大きくバグり散らかすことになろうとは)
注意点が2つ。
・まず、「切る回数を間違えないこと」。
長さ5の木を、長さ5以下にするために必要なカット回数は0です。
余りを計算しておいて、余りが0ならカット回数を1減らす、としましょう。
・次に、「出力予定の値をFloorした値を突っ込んで、達成できるかどうかを見る」などというその場しのぎの実装はしないようにしましょう。
0.5の長さに出来てしまう入力の場合、「丸太の長さを0にしようとして、割り算で無限大を出しWA」になります。
しないようにしようね!(3敗)
F - Range Set Query
F - Range Set Query
問題概要
N個の玉が並んでいて、左からi番目の色はciです。
Q個の範囲について、その中の色の種類数を教えて下さい。
\\(N \\leq 5 \\times 10^5\\)
\\(ci \\leq N \\)
考えたこと
(WAどころか提出すらできていないので、迷走をお楽しみください)
・Queryの問題はSegmentation Treeなんですよ(自信満々)
・セグ木は関数をモノイドにしないといけないので、種類個の大きさのboolの配列を用意して、関数を各要素のORにすればいい。
→結果、bool[50万]を描く要素として持つ配列[524288]を宣言し、手元の環境でもMLEしました。
答えを読むと、「フェンウィックツリー」(New word)というのを使えばいいそうです。これは要復習ですね。
スポンサードリンク