解説
グラフの形の考察
Ai=⌊iφ⌋,Bi=⌊iφ2⌋ とする。
正整数 M に対して Ai≤M を満たす i の個数を考える。
i<φM+1
なので、これを満たす i の個数は ⌊φM+1⌋ である。
同様にして、Bi≤M を満たす i の個数は ⌊φ2M+1⌋ である。
重複を含めると、このグラフの辺の個数 CM は CM=⌊φM+1⌋+⌊φ2M+1⌋
φ2=φ+1 より、φM+1+φ2M+1=M+1 であるため、
CM=M となる。この等式はすべての正整数 M に対して成り立つため、
CM+1−CM=1 となるため Ai=M,Bi=M を満たす正整数 i がちょうど 1 つであると分かる。
よって、数列 A,B には 1,2,…,M が 1 つずつ含まれていることが分かる。
自己ループは無視しても答えは変わらないので i=Ai=1 のときの赤い辺を無視すれば このグラフは木である と分かる。
また、このグラフを頂点 1 を親とする根付き木としてみると、木の高さは ⌈logφN⌉=O(logN) である。
クエリの処理
このグラフは頂点 1 の自己ループを無視すると木なので、白い頂点をすべて連結にするために残すべき辺は一意に定まり、そのような辺は白い頂点どうしを結ぶパスの和集合である。また、残った辺は部分木をなす。
この部分木に含まれる赤色、青色の辺の個数をそれぞれ CR,CB とすると求める答えは RCR+BCB である。
頂点 1 を根とし、根から頂点 v までのパスに含まれる赤色の辺を 0、青色の辺を 1 として、根から順に並べた 01 文字列を Sv とする。木の高さは O(logN) なので、Sv の長さも O(logN) である。
ここで、f(x)=⌊φx⌋ とすると、頂点 v≥2 の親と、その間の辺の色は以下のように求められる。
- f(v+1)−f(v)=1 のとき、親は f(v+1) であり、辺は赤色である。
- そうでないとき、親は v−f(v+1) であり、辺は青色である。
したがって、親を繰り返し求めることで、各頂点の Sv を O(logN) で求められる。
頂点を Sv の辞書順に並べると、赤色の辺を優先して DFS したときの訪問順と一致する。
白い頂点の個数を k とする。白い頂点を Sv の辞書順に並べたものを v1,v2,…,vk とし、vk+1=v1 とする。
頂点 u,v 間のパスに含まれる赤色の辺、青色の辺の個数をそれぞれ dR(u,v),dB(u,v) とすると
CR=21i=1∑kdR(vi,vi+1), CB=21i=1∑kdB(vi,vi+1) が成り立つ。
黒色の頂点 v を白色にするときを考える。頂点を Sv の辞書順に並べたとき、v の直前、直後の白い頂点をそれぞれ s,t とすると
クエリを処理する前では s→t のパスだったものが、クエリを処理した後では s→v→t になる。
したがって、赤色と青色両方について C+=21(d(s,v)+d(v,t)−d(s,t)) と更新すればよい。白色の頂点を黒色にするときはこの逆を行えばよい。
また、Su,Sv の最長共通接頭辞は頂点 u,v の最小共通祖先までのパスを表すため、dR,dB は文字列の比較によって O(logN) で求められる。
白い頂点の Sv をset などで管理すれば、頂点の追加・削除は O(logQlogN) で行える。辺の重みを変更するクエリでは CR,CB は変化しないため、重みだけを更新すればよい。
よって、クエリあたり O(logQlogN)、合わせて O(QlogQlogN) でこの問題を解くことができた。