2021年3月17日水曜日

ARC 065 E - へんなコンパス

a,ba, bの距離をDDとする。全体を45度回転してチェビシェフ距離の問題に読み替えると、1つの点(x,y)(x, y)から距離DDにある点はx±D,y±Dx \pm D , y\pm Dで定まる正方形の辺上にある。したがって、

  • v[t]:=xv[t] := x座標をttとする点をyy座標の昇順に並べた列
  • h[t]:=yh[t] := y座標をttとする点をxx座標の昇順に並べた列

を持っておけば、(x,y)(x, y)から距離DDにある点の数は4つの列v[x±D],h[y±D]v[x \pm D], h[y \pm D]の二分探索で数えられる。

ただ、問題が要求しているのは、単にマンハッタン距離がDDであるような点のペアを数えることではなく、そのような点を結ぶ無向辺があるようなグラフを考えた時、辺{a,b}\{a, b\}を含む連結成分について同じ量を数えることである。

ただ、この設定でもBFSをしながら同じことをやればよいように見える。つまり、aaを始点にして、上記の数え上げをしながら距離DDにある点をキューに入れていけばよい……が、これを素朴にやるとΩ(N2)\Omega (N^2)になってしまう。o(N2)o(N^2)で数えるには、一度見た頂点を再び走査しないようにするために、その都度消していく必要がある。

そこで、h(t),v(t)h(t), v(t)をそれぞれ昇順の配列hs(t),vs(t)h_s(t), v_s(t)と平衡二分木hb(t),vb(t)h_b(t), v_b(t)の二通りで持つことにする。キューから点(x,y)(x, y)を初めて取り出した時、次の処理をする:

  • (x,y)(x, y)をすべての平衡二分木から消去する。
  • vb[xD],vb[x+D],hb[yD],hb[y+D]v_b[x - D], v_b[x+D], h_b[y - D], h_b[y+D]からそれぞれ区間[yD,y+D],[yD,y+D],[xD,x+D],[xD,x+D][y-D, y+D], [y-D, y+D], [x-D, x+D], [x-D, x+D]に対応する4列をsplitして取り出す。vb[xD],vb[x+D],hb[yD],hb[y+D]v_b[x - D], v_b[x+D], h_b[y - D], h_b[y+D]には残った左右の区間をmergeして入れておく。
  • 4つの列上の頂点をすべてキューに入れ、vb,hbv_b, h_bからすべて除く。
  • (x,y)(x, y)と4つの列上の点によるペアを数える。
    • 配列vs[xD]v_s[x-D][yD,y+D][y-D, y+D]に対応する区間の長さを結果に加算する。
    • 配列vs[x+D]v_s[x+D][yD,y+D][y-D, y+D]に対応する区間の長さを結果に加算する。
    • 配列vs[yD]v_s[y-D][xD,x+D][x-D, x+D]に対応する区間の長さを結果に加算する。
    • 配列vs[y+D]v_s[y+D][xD,x+D][x-D, x+D]に対応する区間の長さを結果に加算する。
    • 正方形の4頂点(x±D,y±D)(x \pm D, y \pm D)に穴が存在する場合は2回数えているので、重複を引く。

すべてのペアを2回ずつ数えているので、最後に2で割ることに注意。