CF 813 E - Army Creation
問題
問題概要
長さの数列と整数が与えられる。次のようなクエリが個与えられるので、それに答えよ:
- クエリ : 区間 について、同じ値は個までしか選べない時に、最大で何個まで選べるか
(問題を読んでもらうと分かるが、オンラインクエリになっている)
アイデア
オフラインクエリだったら、クエリを先読みしてMoを使ってmapで頻度数えて終わりだったのに...と思った。
クエリごとに、各値について先頭から個を選ぶということを考えよう。番目の要素が選ばれるには、そもそもでないといけないし、からスタートしてそれまでの間にと同じ値が個現れていてはいけないということになる。
ここで、新たな数列を作る。の番目の要素の値は、a[i]と同じ値で、k個前にあるindex(b=なければ-1)
というものである。すると、番目の要素が選ばれるということはであることと、と言える。
あとは、区間 について、である要素がいくつあるかを数えれば良い。これは、mergesortの過程を保存したようなSegmentTreeなどで各ノードで二分探索をすればできたりする。
今回は(SegmentTreeの実装をサボりたかったので)平方分割した。
実装(C++)
続きを読むCF 712 E - Memory and Casinos
問題
問題概要
個のカジノが一列に並んでいる(左から番目のカジノをカジノと呼ぶ)。カジノで遊んだ時に、勝つと1つ右に移動する。このときに勝つ確率はである。負けると1つ左に移動する(勝率は)。番目の左側と番目の右側は出口である。
また、区間に対して、次の条件を満たしている時、区間をdominate
すると呼ぶ:
- 番目のカジノからスタートする。
- 番目のカジノでは絶対に負けない。
- 番目のカジノで勝ち、右に移動して終了する。
次の2種類のクエリを考える:
- クエリ1 : が与えられるので、をにセットする。
- クエリ2 : が与えられるので、区間を
dominate
できる確率を答える。
以上のクエリが合計で個与えられるので順に処理せよ。
- どの状況でも、が成り立つ。
アイデア
区間を管理するために、SegmentTreeを使って高速に処理することを考える。区間のマージをどうするかを考える。
この上の2つの確率を定義して、区間と区間をマージして区間の結果を得ることを考える。とおくと、この4つを使っての値を表すことが出来る。
まず、を求める。これは、との間を何回またぐことになるかで場合分けをすることが出来る。1回またぐのは、ストレートに両区間でdominate
できれば良いのでとなる。次は、3回またぐパターンだが、これは([i,k]をdominate) → ([k+1,j]でdominate失敗) → ([i,k]でkスタートで耐えてk+1へ) → ([k+1,j]でdominate)
という流れになる。この確率は、である。以降またぐ回数が5, 7, 9, ... 回と無限に続き、これは初項、公比の無限等比級数であるから、である。
次に、を求める。これも上で考察したことと同様に、との間を何回またぐことになるか(0, 2, 4, 6, ...回)で場合分けをすることが出来る。0回のときだけは特別で、で、2回以降は初項、公比の無限等比級数であるから、である。