目次

AtCoder Regular Contest 148 B,C,D問題メモ

AtCoder Regular Contest 148

B - dp

B - dp

問題

解法

なるべく先頭から続く'd'を多くするのが正義。

「最初に出てきた'p'」の位置を、回転させる区間の左端 $L$ に設定して問題ない。

dddppdppppd
   L

区間の右端 $R$ は、以下の2通りが考えられる。

ddd ppp d pppp d pp dd pppp d
    L 2      1            1

2.が見落としがち?だが、こいつだけは「区間全てを'd'にする」ことができるので、その後に続く'd'を含めることができ、最適となる場合がある。

ddd pp dddddddddddddddddddddddddddddddd pppp d pppp d
    ~~
    ここだけをひっくり返すのがいい

可能性のある箇所を全て試しても、その箇所が $O(|S|)$、1回の判定で $O(|S|)$ なので、$O(|S|^2)$ で通る。

Python3

C - Lights Out on Tree

C - Lights Out on Tree

問題

解法

言い換え

簡単な場合として木でなく直線だった時を考える。操作は以下のようになる。

このような操作は、隣り合う箇所との差分(同じか異なるか。XORと捉えてもよい)に注目すると「そこと1つ前の差分の状態のみを変更し、他は変えない」といえる。

    1 2 3 4 5 6 7
(1) 1 0 0 0 1 1 0    0:表 1:裏
      ^     ^   ^

従って操作回数は「表と裏が隣接する部分」の個数に一致する。
今回、最終的には全て裏にしないといけないが、 頂点 $1$ の親には必ず裏である頂点 $0$ が隠れていると考えると上手く表現できる。

木に戻しても似たようなことが言えて、1回の操作は 「自身と親との差分の状態のみを変更する」ので、答えはそのような箇所の個数と一致する。

答えの求め方

上記を踏まえると、以下のようなアルゴリズムが考えられる。

正しい答えは求まるが、これだとTLEとなる。

もし $v$ がめっちゃ多くの頂点と隣接するハブ頂点で、$Q$ 回のクエリでそればかり指定されると、 調べる $u$ の個数が $O(NQ)$ となってしまうからである。

高速化する。

ハブ頂点をたとえば「隣接頂点が $\sqrt{N}$ 個以上の頂点」として分類する。

さらに、各頂点の隣接リストも「ハブ頂点」「ハブ頂点以外」の2つに分類しておく。

木におけるハブ頂点の個数は少ないので、隣接する「ハブ頂点」はどの頂点も高が知れている。
隣接する「ハブ頂点以外」が、ハブ頂点は多い状態となっている。

こうすると、1回のクエリで辿る上限が $O(|S|\sqrt{N}))$ となり、クエリ全体の $|S|$ の総和を $M$ として $O(M \sqrt{N})$ となる。

(後から考えると、親だけ別に管理して「隣接頂点はとりあえず全て足す」「親も $S$ に含まれたら双方で足しすぎなので2引く」でよかったね)

Python3

D - mod M Game

D - mod M Game

問題

解法

最終局面を考える

残った数が2つになった時、先攻がどちらを取っても負けてしまうのは、どのような状況だろうか?

これまでの和を $a,b$、残っている数を $c,d$ とする。

$a+c \equiv b+d \mod{M}$ かつ $a+d \equiv b+c \mod{M}$ が同時に成り立つ。

整理すると、$2c \equiv 2d \mod{M}$ となる。このような状況に後攻は持ち込みたい。

$M$ が奇数の時

$2c \equiv 2d \mod{M}$ となる $(c,d)$ を考える。

$2c,2d$ は $2M$ 未満なので、$c \neq d$ の場合、$2c+M=2d$ である(大小関係がどちらというのはあるが)。

$M$ が奇数なら偶奇が合わないので明らかに矛盾しており、結局、$c=d$ の場合しか無いことがわかる。

従ってそれまでの和 $a,b \mod{M}$ も同じである必要があり、1つ少ない状態に帰着できる。

再帰的に考えると、後攻は「全ての数が偶数個ずつある場合のみ、先攻と同じ数を取り続けることで勝てる」ことがわかる。

$M$ が偶数の時

$c \neq d$ の場合でも $2c \equiv 2d \mod{M}$ に解があり得る。
$M=6$ のとき、$(0,3),(1,4),(2,5)$ という、$(i, i+\frac{M}{2})$ という組が $(c,d)$ になりえる。

このような組が残っていた場合、それまでの和 $a,b$ も ちょうど $\frac{M}{2}$ だけ離れていた場合に、両者の和 $\mod{M}$ が同じとなる。
大小関係はどちらでもよい。

つまり、$\frac{M}{2}$ だけ離れた組が $(0,3,1,4)$ のように偶数個あれば、「0なら3、1なら4」のように先攻が選んだペアの片割れを選び続ければ、後攻が勝てると言うことになる。

もちろん、同じ数($c=d$)がある場合はそれで打ち消してもいい。

$\frac{M}{2}$ だけ離れている2数をペアとして、ペア毎に考えればよい。

個数カウントして、上記の通りに調べればよい。

$p,q$ の偶奇が違うようなペアがあると先攻必勝という証明

数は偶数個あるので、どちらかが余るようなペアは偶数個存在するはずである。

この余る数を上手く組み合わせることで、和が同じになって後攻が勝ってしまわないか?
結論から言うと、それはない。

よって、

よって先攻必勝である。

Python3