コンテスト中AC:A,B
Cはコンテスト後自力AC
A - Bridge and Sheets
便宜上、を追加しておきます。
最初からかけられているシートのうち、最も右端をとします。最初
としておきます。
にかけられたシートを考えるとき、前のシートの右端
から
までがシートがかけられていない区間です。
これより、シートがの長さ分必要になるので、
がこの区間で必要なシートの枚数です。なお、シートが重なっていた場合に長さが負になってしまうので、0とmaxをとっています。
のシートの右端は、
なので、
と更新します。
この操作をi = 1からN+1まで繰り返し、シートの枚数を足し合わせていけば、それが答えです。
提出コード
B - Reserve or Reverse
交換の優先度はインデックスが小さい方が高いので、交換するかどうかをi = 1から順に考えます。
と交換する対象
は以下の条件を満たすようなものを貪欲に決定できます。
- 辞書順で
より小さい
- 辞書順で最も小さい
である
を既に交換していた場合、
である
- 最も後ろに出現する
1は自明だと思います。
2ですが、1を満たす中では、辞書順でできるだけ小さい文字を持ってきた方が全体の辞書順を小さくできます。
3ですが、これまで交換対象としたものより、内側である必要があります。(2と8既にを交換していたら、3〜7の中から選ぶ必要がある)
4ですが、3の条件からわかるように次以降に選ぶ交換対象は今選んだものの内側になってしまいます。そこで、1,2の条件を同時に満たす文字が複数個あった場合、次以降の候補をできるだけ増やす為に、できるだけ出現位置が後ろのものを選ぶのが良いです。
条件を満たすものを得る方法ですが、Segment Treeが使えます。
例えば、AtCoder Libraryのsegtreeであれば、の組を記録し、二項演算op、単位元eを以下のように定めておきます。
:
なら、小さい方を返す。そうでなければ、
の大きい方を返す。
単位元はなどとしておけば良いです。
提出コード
こちらの実装では、交換対象を左端と右端から考えていくイメージで、を右側で交換した中で最も小さいものとして記録しています。
C - The Majority
条件を満たす箱の入れ方の一つを例にしてみます。
箱1:1 1 1 1 2 2 2
箱2:1 1 1 3 3
箱3:1 1 4
箱4:1
ここから、
- 1以外の数字があれば、必ずそれに対応する1が存在する
- 各箱につきペアとなった1を除いた1が少なくとも1つ存在する
ことが言えます。
1の個数をとし、1以外の個数を
と名づけます。
1つ目の考察から、が成り立つ必要があるので、これが成り立たない時、0通りです。成り立つ場合、ペアを作るので、その分の1の個数を減らして、
としておきます。
2つ目の考察から、ペア以外の1を各箱に少なくとも1つ入れないといけないので、予め各箱に1つずつ分配しておきます。従って、である必要があります。これが成り立たないとき、0通りです。
成り立つ場合、1の個数を減らして、
とします。
後は、1の残り及び、1とペアになった各数字を箱にいれていきます。1やペアは区別がないので、これを区別のある箱に入れる組み合わせは、重複組み合わせです。1または1とペアの各数字の個数を個とすると、
です。
これを各数字について求めていくわけですが、
なので、で分子分母が求まります。
分母は、の乗法逆元を求める必要がありますが、フェルマーの小定理に基づいて
で求めることができます。
ある数字の入れ方それぞれについて他の数字の入れ方が存在するので、上で求めたものの総積を求めると答えになります。
計算量は、各数字について重複組み合わせを計算する必要があるので、です(多分)。
提出コード