ひとりで勝手にはじめた蟻本読書会 ギリギリを考える計算幾何 蟻本読書会 の続きです。

Coneology (POJ No.2932)

Coneology (POJ No.2932)

2次元平面上にN個の円があります。i番目の円は中心が(x_i, y_i)で半径がr_iであり、これらの円は互いに共有点を持ちません。最も外側にある円をすべて求めよ。

入力されるデータ
N
r_1 x_1 y_1
r_2 x_2 y_2

r_N x_N y_N
(ただし、1 ≦ N ≦ 40000 )

どの点も共有点を持たないのである円が別の円の内部に含まれているかどうかの判定は、2 円の中心の距離と円の半径を比較することで可能です。

平面走査とは走査線という直線を動かしながら、走査線と交わる部分の情報を少しずつ更新していくことにより全体の計算をおこないます。

この問題の場合、Y軸に平行な走査線を左から右へ動かしつつ、もっとも外側にある円のうちで走査線と交わっているものの一覧を更新していくことを考えます。走査線を左から右へ動かした場合、円との交わりが変更されるのは走査線が円の左側か右側にきたときに限定されます。

ある円の左側に走査線がきたときには、その円がすでに走査線と交わっているものの一覧内の円に含まれているか判定しなければなりません。このとき実際に判定処理をおこなう必要があるのはその円からみて上下それぞれの方向で一番近い円だけで構わないことに気が付きます。もしその円がY座標が一番近い円には含まれず、ふたつ以上離れた円には含まれる場合、ふたつの円が交わってしまうからです。

ここでは指定されたY座標から上方向と下方向で一番近い円を取得できるデータ構造が必要です。要素を追加するときにソートされた状態を維持できるように二分探索法で挿入位置を取得します。またY座標が一番近い円を取得するときも二分探索法で該当する円を探します。

Eventクラス

走査線を移動させていくわけですが、そのX座標と格納されている座標はどの円の座標なのか?円の左側なのか右側なのかがわかるようにしておきます。

Pairクラス

円のY座標を格納します。同時にどの円のY座標なのかがわかるようにしています。

G – 村

似たような問題がAtCoderにあります。

G – 村

きつねのしえるは休暇でとある小さな村を訪れている。彼女が驚いたのはその村の表札がもつ性質である。

村には N 個の家屋がある。簡単のため村は 2 次元平面であるとし、家屋はこの平面上の点であると見なす。それぞれの家屋には表札が 1 個設けられており、その家の苗字を表していた。しえるは村の中を訪問するにつれてこの村の表札が次のような性質を持っていることに気付いた。

ある実数 R が存在する。
もし 2 つの家屋の距離が R 以下であるなら、その 2 つの家屋は同じ表札を持つ。
もし 2 つの家屋の距離が 3R 以上であるなら、その 2 つの家屋は異なる表札を持つ。
任意の 2 つの家屋の距離は R 以下であるか 3R 以上であるかのどちらかである。
距離は平面上のユークリッド距離によって計測するものとする。

しえるはこの村に表札が全部で何種類あるのかが気になったが、この村は意外に広いということに気付いたので、計算機を使ってこの答えを模索することにした。

入力されるデータ
N R
x_1 y_1
x_2 y_2

x_N y_N

(ただし、1 ≦ N ≦ 2 * 10^5
1 ≦ R ≦ 10^3
|x_i|, |y_i| ≦ 10^6
N は整数である.
R, x_i, y_i は実数で小数第 3 位まで表される)

家屋を中心に半径 R の円を書きます。走査線を左から順に移動させて円の左側が接したら、すでに走査線と交わっているものの一覧内の円のなかにその円の中心が入っていないかを調べます。入っていなければ異なる表札をもつ家屋が発見されたことになります。この場合も一覧内の円すべてを調べる必要はなく、じっさいに調べるのはその円よりも Y 座標が大きいものと小さいものそれぞれのなかでその円にもっとも近い円のふたつだけです。

距離を比較するときにそのまま比較しようとすると誤差で Wrong Answer になってしまいます。「任意の 2 つの家屋の距離は R 以下であるか 3R 以上であるかのどちらかである」という条件があるのでやや広めにとって誤差に対応します。

入力されるデータが違うだけでほとんど解法は同じです。