点a,bの距離をDとする。全体を45度回転してチェビシェフ距離の問題に読み替えると、1つの点(x,y)から距離Dにある点はx±D,y±Dで定まる正方形の辺上にある。したがって、
- v[t]:=x座標をtとする点をy座標の昇順に並べた列
- h[t]:=y座標をtとする点をx座標の昇順に並べた列
を持っておけば、(x,y)から距離Dにある点の数は4つの列v[x±D],h[y±D]の二分探索で数えられる。
ただ、問題が要求しているのは、単にマンハッタン距離がDであるような点のペアを数えることではなく、そのような点を結ぶ無向辺があるようなグラフを考えた時、辺{a,b}を含む連結成分について同じ量を数えることである。
ただ、この設定でもBFSをしながら同じことをやればよいように見える。つまり、aを始点にして、上記の数え上げをしながら距離Dにある点をキューに入れていけばよい……が、これを素朴にやるとΩ(N2)になってしまう。o(N2)で数えるには、一度見た頂点を再び走査しないようにするために、その都度消していく必要がある。
そこで、h(t),v(t)をそれぞれ昇順の配列hs(t),vs(t)と平衡二分木hb(t),vb(t)の二通りで持つことにする。キューから点(x,y)を初めて取り出した時、次の処理をする:
- 点(x,y)をすべての平衡二分木から消去する。
- vb[x−D],vb[x+D],hb[y−D],hb[y+D]からそれぞれ区間[y−D,y+D],[y−D,y+D],[x−D,x+D],[x−D,x+D]に対応する4列をsplitして取り出す。vb[x−D],vb[x+D],hb[y−D],hb[y+D]には残った左右の区間をmergeして入れておく。
- 4つの列上の頂点をすべてキューに入れ、vb,hbからすべて除く。
- (x,y)と4つの列上の点によるペアを数える。
- 配列vs[x−D]の[y−D,y+D]に対応する区間の長さを結果に加算する。
- 配列vs[x+D]の[y−D,y+D]に対応する区間の長さを結果に加算する。
- 配列vs[y−D]の[x−D,x+D]に対応する区間の長さを結果に加算する。
- 配列vs[y+D]の[x−D,x+D]に対応する区間の長さを結果に加算する。
- 正方形の4頂点(x±D,y±D)に穴が存在する場合は2回数えているので、重複を引く。
すべてのペアを2回ずつ数えているので、最後に2で割ることに注意。