baekjoon 16192. Voronoi Diagram Returns
๋ฌธ์ ์ถ์ฒ
2018 KAIST 8th ACM-ICPC Mock Competition L๋ฒ
๋ฌธ์ ๋ฒ์ญ
๋ค์์ ์ ๊ฐ ์์๋ก ๋ฒ์ญํ ๋ด์ฉ์ ๋๋ค.
๋ฌธ์

๊ทธ๋ฆผ: ํฌ๊ธฐ 4์ ๋ณด๋ก๋ ธ์ด ๋ค์ด์ด๊ทธ๋จ.
2์ฐจ์ ์ง๊ต ์ขํ๊ณ์์, ๋น์ด ์์ง ์์ ์ ์ ์งํฉ $S$์ ๋ํ ๋ณด๋ก๋ ธ์ด ๋ค์ด์ด๊ทธ๋จ(Voronoi Diagram)์ ํ๋ฉด์ โ์ด ์์น์์ ๊ฐ์ฅ ๊ฐ๊น์ด ์ ์ด ๋ฌด์์ธ๊ฐ?โ๋ผ๋ ๊ธฐ์ค์ผ๋ก ๋๋ ๋ํ์ด๋ค.
์ข ๋ ์ ํํ ๋งํ๋ฉด, ์ ์ ์งํฉ ${P_1, P_2, \cdots, P_n}$์ ๋ํ ๋ณด๋ก๋ ธ์ด ๋ค์ด์ด๊ทธ๋จ์ ์ฌ๋ฌ ๊ฐ์ ์์ญ์ผ๋ก ๋๋๋ฉฐ, ์์์ ์ $K$๊ฐ $i$๋ฒ ์์ญ์ ์ํ๋ค๋ ๊ฒ์ ๋ค์ ์กฐ๊ฑด์ ๋ง์กฑํ ๋์ด๋ค.
๋ชจ๋ $1 \le j \le n$์ ๋ํ์ฌ, ์ $K$์ $P_i$ ์ฌ์ด์ ์ ํด๋ฆฌ๋ ๊ฑฐ๋ฆฌ๊ฐ ์ $K$์ $P_j$ ์ฌ์ด์ ๊ฑฐ๋ฆฌ๋ณด๋ค ์๊ฑฐ๋ ๊ฐ์์ผ ํ๋ค. ์ฆ, $d(P_i, K) \le d(P_j, K)$์ด๋ค.
์ฌ๊ธฐ์ $d(X, Y)$๋ ์ $X$์ ์ $Y$ ์ฌ์ด์ ์ ํด๋ฆฌ๋ ๊ฑฐ๋ฆฌ์ด๋ค.
์๋ฅผ ๋ค์ด, ์ ๊ทธ๋ฆผ์์๋ ํ๋ฉด์์ ๋ชจ๋ ์์น๊ฐ ๊ฐ์ฅ ๊ฐ๊น์ด ์ ์ ๋ฐ๋ผ ์์น ๋์ด ์๋ค.
ํ๋์ ์์ญ์๋ง ์ํ๋ ์ ์ ๋ฐ์ ์์ผ๋ก, ๋ ๊ฐ ์ด์์ ์์ญ์ ๋์์ ์ํ๋ ์ ์ ๊ฒ์ ์ ์ด๋ ์ ์ผ๋ก ๋ํ๋๋ค.
$\mathcal{O}(n \log n)$ ์๊ฐ์ ๋ณด๋ก๋
ธ์ด ๋ค์ด์ด๊ทธ๋จ์ ๊ตฌ์ฑํ๋ ์๊ณ ๋ฆฌ์ฆ์ด ์กด์ฌํ์ง๋ง, ์ด ์๊ณ ๋ฆฌ์ฆ์ ๊ตฌํ์ด ๋ณต์กํ๊ณ ์ด๋ ต๊ธฐ๋ก ์ ๋ช
ํ๋ค.
ํ์ง๋ง ์ฐ๋ฆฌ๋ ๋๊ทธ๋ฌ์ด ์ถ์ ์์ด๋ฏ๋ก, $n \le 2000$๋ง ์ฃผ์ด์ง๋ฉฐ, ์ด๋ ๋ ๋๋ฆฐ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํด๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค.
์ด ๋ฌธ์ ์์๋ ๋ณด๋ก๋
ธ์ด ๋ค์ด์ด๊ทธ๋จ ์์์ ์ฃผ์ด์ง ์ฟผ๋ฆฌ์ ์ ์ด ์ด๋ ์์ญ์ ์ํ๋์ง๋ฅผ ํ๋จํ๋ ์ ์ฟผ๋ฆฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด์ผ ํ๋ค.
์ ์ ์งํฉ ${P_1, P_2, \cdots, P_n}$์ผ๋ก ๊ตฌ์ฑ๋ ๋ณด๋ก๋
ธ์ด ๋ค์ด์ด๊ทธ๋จ๊ณผ $q$๊ฐ์ ์ ์ฟผ๋ฆฌ๊ฐ ์ฃผ์ด์ง ๋, ๊ฐ ์ ์ฟผ๋ฆฌ ์ ๋ํด ๋ค์ ์ค ์ด๋์ ์ํ๋์ง๋ฅผ ํ๋ณํด์ผ ํ๋ค:
- ์ด๋ค ์์ญ์๋ ์ํ์ง ์์ผ๋ฉด
NONE
์ ์ถ๋ ฅํ๋ค. - ์ ํํ ํ๋์ ์์ญ์๋ง ์ํ๋ฉด
REGION X
๋ฅผ ์ถ๋ ฅํ๋ค. ์ฌ๊ธฐ์ $X$๋ ํด๋น ์์ญ์ ์ธ๋ฑ์ค์ด๋ค. - ์ ํํ ๋ ๊ฐ์ ์์ญ์ ์ํ๋ฉด
LINE X Y
๋ฅผ ์ถ๋ ฅํ๋ค. ์ฌ๊ธฐ์ $X$์ $Y$๋ ํด๋น ๋ ์์ญ์ ์ธ๋ฑ์ค์ด๋ฉฐ, $X < Y$๋ฅผ ๋ง์กฑํด์ผ ํ๋ค. - ์ธ ๊ฐ ์ด์์ ์์ญ์ ์ํ๋ฉด
POINT
๋ฅผ ์ถ๋ ฅํ๋ค.
์ ๋ ฅ
์ฒซ์งธ ์ค์ ๋ณด๋ก๋
ธ์ด ๋ค์ด์ด๊ทธ๋จ์ ๊ตฌ์ฑํ๋ ์ ์ ๊ฐ์ $n$๊ณผ ์ฟผ๋ฆฌ์ ๊ฐ์ $q$๊ฐ ์ฃผ์ด์ง๋ค.
($3 \le n \le 2, 000,\ 1 \le q \le 250, 000$)
๋ค์ $n$๊ฐ์ ์ค์๋ ๊ฐ ์ $P_i$์ $x$, $y$ ์ขํ๊ฐ ์ฃผ์ด์ง๋ค. ์ด ์ ๋ค์ ๋ณด๋ก๋
ธ์ด ๋ค์ด์ด๊ทธ๋จ์ ๊ตฌ์ฑํ๋ ์ ๋ค์ด๋ค.
๋ชจ๋ ์ ์ ์๋ก ๋ค๋ฅด๋ค. ($|x|,\ |y| \le 10,000$)
$j$๋ฒ์งธ ์ค๋ถํฐ, $q$๊ฐ์ ์ค์๋ ๊ฐ ์ ์ฟผ๋ฆฌ $Q_j$์ $x$, $y$ ์ขํ๊ฐ ์ฃผ์ด์ง๋ค.
๊ฐ ์ ์ฟผ๋ฆฌ์ ๋ํด, ํด๋น ์ ์ด ์ด๋ ๋ณด๋ก๋
ธ์ด ์์ญ์ ์ํ๋์ง ํ๋จํด์ผ ํ๋ค. ($|x|,\ |y| \le 10,000$)
์ถ๋ ฅ
์ถ๋ ฅ์ ์ด $q$์ค๋ก ๊ตฌ์ฑ๋๋ค.
$j$๋ฒ์งธ ์ค์๋ ๋ค์ ์ค ํ๋๋ฅผ ์ถ๋ ฅํด์ผ ํ๋ค.
- ๋ง์ฝ $Q_j$๊ฐ ์ด๋ค ์์ญ์๋ ํฌํจ๋์ง ์๋๋ค๋ฉด,
NONE
์ ์ถ๋ ฅํ๋ค. - ๋ง์ฝ $Q_j$๊ฐ ์ ํํ ํ๋์ ์์ญ์ ํฌํจ๋์ด ์๋ค๋ฉด,
REGION X
๋ฅผ ์ถ๋ ฅํ๋ค. ์ฌ๊ธฐ์ $X$๋ ํด๋น ์์ญ์ ์ธ๋ฑ์ค์ด๋ค. - ๋ง์ฝ $Q_j$๊ฐ ์ ํํ ๋ ์์ญ์ ํฌํจ๋์ด ์๋ค๋ฉด,
LINE X Y
๋ฅผ ์ถ๋ ฅํ๋ค. ์ฌ๊ธฐ์ $X$์ $Y(X < Y)$๋ ํด๋น ๋ ์์ญ์ ์ธ๋ฑ์ค์ด๋ค. - ๋ง์ฝ $Q_j$๊ฐ 3๊ฐ ์ด์์ ์ง์ญ์ ํฌํจ๋์ด ์๋ ๊ฒฝ์ฐ
POINT
๋ฅผ ์ถ๋ ฅํ๋ค.
ํ์ด
๋ณด๋ก๋ ธ์ด ๋ค์ด์ด๊ทธ๋จ(voronoi diagram)์ ์ดํดํ๊ณ ์์ผ๋ฉด ๋ฌธ์ ๋ฅผ ๊ธ๋ฐฉ ์ดํดํ ์ ์์ต๋๋ค. voronoi diagram์ด๋ ๊ฐ๋จํ๊ฒ ๋งํ์๋ฉด ํ๋ฉด์ ํน์ ์ ๊น์ง์ ๊ฑฐ๋ฆฌ๊ฐ ๊ฐ์ฅ ๊ฐ๊น์ด ์ ์ ์งํฉ์ผ๋ก ๋ถํ ํ ๊ทธ๋ฆผ์ ๋๋ค. ๋คํํ๋ ๋ฌธ์ ์์ ์ค๋ช ์ ์ฝ๊ฒ ํด์ค์ ์ฌ์ ์ง์ ์์ด๋ ํ ์ ์์ต๋๋ค.
์๋๋ผ๋ฉด ๋ณด๋ก๋ ธ์ด ๋ค์ด์ด๊ทธ๋จ ๋ฌธ์ ๋๋ก ํ์ด์ผํ์ง๋ง, ์ด ๋ฌธ์ ๋ ๋๊ทธ๋ฌ์ด ์ถ์ ์ ๋ถ๋ค์ด ์๊ฐ์ ํ์ ๋ฌด๋ ค 10์ด๋ก ๋ง๋ค์ด์ฃผ์ จ๊ธฐ ๋๋ฌธ์ ์ฟผ๋ฆฌ๋น $O(n)$์ ํ ์ ์์ต๋๋ค. ํ์ฌ ์ ์์ ๊ฐ์ฅ ๊ฐ๊น์ด ์ ๋ค์ ๊ฐ์๋ฅผ countํ์ฌ ๊ทธ ๊ฐ์์ ๋ฐ๋ผ ๋ฌธ์ ์์ ์๊ตฌํ๋ ์ถ๋ ฅ์ ์คํํ๋ฉด ๋๋ ๊ฐ๋จํ ๋ฌธ์ ์ ๋๋ค.
์ฟผ๋ฆฌ๋ง๋ค ๋ณด๋ก๋ ธ์ด ๋ค์ด์ด๊ทธ๋จ์ ๊ตฌ์ฑํ๋ $n$๊ฐ์ ์ ์ ๋ฐ๋ณต๋ฌธ์ ๋๋ฉฐ ํด๋น ์ฟผ๋ฆฌ ์ ์์์ ์ ํด๋ฆฌ๋ ๊ฑฐ๋ฆฌ๊ฐ ๊ฐ์ฅ ์์ ๊ฐ์ ์ ์ฅํ๊ณ , ์ธ๋ฑ์ค๋ฅผ ๋ฐฐ์ด์ ์ ์ฅํฉ๋๋ค. ๋ง์ฝ ์ ํด๋ฆฌ๋ ๊ฑฐ๋ฆฌ๊ฐ ์ ์ฅ๋ ์ต์๊ฐ๊ณผ ๊ฐ๋ค๋ฉด ์ธ๋ฑ์ค๋ฅผ ๋ฐฐ์ด์ ์ถ๊ฐํฉ๋๋ค. ์ดํ ์ธ๋ฑ์ค ๋ฐฐ์ด์ ํฌ๊ธฐ์ ๋ฐ๋ผ ์ถ๋ ฅ์ ์คํํฉ๋๋ค.
์ ์ฒด ์ฝ๋
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int n, q;
cin >> n >> q;
vector<pair<int, int>> coordinate(n);
for(int i = 0; i < n; i++)
cin >> coordinate[i].first >> coordinate[i].second;
while(q--) {
int qx, qy;
cin >> qx >> qy;
int minDist = 1e9;
vector<int> idx;
for(int j = 0; j < n; j++) {
int dx = qx - coordinate[j].first;
int dy = qy - coordinate[j].second;
int dist = dx*dx + dy*dy;
if(dist < minDist) {
minDist = dist;
idx = {j};
}
else if(dist == minDist) idx.emplace_back(j);
}
if(idx.empty()) cout << "NONE" << '\n';
else if(idx.size() == 1) cout << "REGION" << ' ' << idx[0]+1 << '\n';
else if(idx.size() == 2) cout << "LINE" << ' ' << idx[0]+1 << ' ' << idx[1]+1 << '\n';
else cout << "POINT" << '\n';
}
return 0;
}
Comments