kd-tree 题目:
Description
Given n points in 2-dimensional plane. For each point p, we can draw a circle with center p and radius r (r is the
distance between point p and the kth nearest point (except p) of p). Now we need to select m points from the n
points, such that the m circles generated by the selected m points are the largest m ones. If there are two circles
which have the same radius, then select the one with smaller id. Please calculate the area of the union region
of the m circles.
Note 1: The distance we use in this problem is the Euclidean distance, that is to say, if there are two points
p(x1, y1) and q(x2, y2), then the distance of p and q is:
dis(p,q)=dis(q,p)=sqrt( (x1-x2)^2 + (y1-y2)^2 );
Note 2: If point p is input earlier than point q, then we say point p has a smaller id.
Input
The first line contains only one positive integer T (T <= 15), representing there are T cases below.
For each case, the first line contains two positive integer n, m (2 <= n <= 100000, 1 <= m <= 1000, m <= n),
representing the number of points in 2dimensional plane and the number of points we need to select.
Then n lines, each line contains three integers x, y, k (-5000 <= x, y <= 5000, 1 <= k <= 10, k < n), representing
the information of one point: (x, y) is the coordinate, and the meaning of k is given in problem description.
We guarantee that all points are distinct.
Output
Each case a line. For each case, print the area of the union of the m circles with 2 digits after decimal point.
Sample Input
1
3 3
0 0 2
1 0 2
2 0 1
Sample Output
14.30
AuthorHu Fan
代码:#include#include #include #include #include using namespace std; const int maxn = 100010; const int maxr = 1010; const double eps = 1e-8; const double EPS = 1e-5; #define Equ(a,b) ((fabs((a)-(b)))<(eps)) #define Less(a,b) (((a)-(b))<(-(eps))) #define LessEqu(a,b) (((a)-(b))<(eps)) #define More(a,b) (((a)-(b))>(eps)) #define MoreEqu(a,b) (((a)-(b))>(-(eps))) int n, m; typedef pair PDD; double x[maxr], y[maxr], r[maxr]; double nx[maxr], ny[maxr], nr[maxr]; double xl[maxr], xr[maxr]; int s[maxr]; struct Point { int x[2]; int k; int dis; int id; int distance(const Point& a) const { int res = 0; for(int i = 0; i < 2; i++) { res += (x[i] - a.x[i]) * (x[i] - a.x[i]); } return res; } bool operator < (const Point& a) const { return dis < a.dis; } }ps[maxn], qs[maxn], tempp; bool cmp_dis(const Point& a, const Point& b) { if(a.dis != b.dis) return a.dis > b.dis; else return a.id < b.id; } int Div[maxn]; int cmpdiv; priority_queue q; bool cmp(const Point& a, const Point& b) { return a.x[cmpdiv] < b.x[cmpdiv]; } void Build_kdTree(int l, int r, Point* p, int depth) { if(l > r) return; int mid = (l + r) >> 1; Div[mid] = depth % 2; cmpdiv = Div[mid]; nth_element(p + l, p + mid, p + r + 1, cmp); Build_kdTree(l, mid - 1, p, depth + 1); Build_kdTree(mid + 1, r, p, depth + 1); } void Query(int l, int r, Point* p, Point a) { if(l > r) return; int mid = (l + r) >> 1; tempp = p[mid]; tempp.dis = a.distance(tempp); if(tempp.dis != 0) { if(q.size() < a.k) q.push(tempp); else if(tempp.dis < q.top().dis) { q.pop(); q.push(tempp); } } int d = a.x[Div[mid]] - tempp.x[Div[mid]]; int l1 = l, r1 = mid - 1; int l2 = mid + 1, r2 = r; if(d > 0) l1 ^= l2 ^= l1 ^= l2, r1 ^= r2 ^= r1 ^= r2; Query(l1, r1, p, a); if(q.size() < a.k || d * d < q.top().dis) { Query(l2, r2, p, a); } } inline bool cmp1(int a,int b) { if(Equ(x[a] - r[a], x[b] - r[b])) return Less(x[a] + r[a], x[b] + r[b]); return Less(x[a] - r[a], x[b] - r[b]); } inline bool cmp0(int a, int b) { return More(r[a], r[b]); } int L, R; PDD se[maxr]; inline double f(double v) { int sz = 0, i, j; double ret = 0.0; for(i = L; i < R; ++i) { if(LessEqu(v, xl[i]) || MoreEqu(v, xr[i])) continue; j = s[i]; double d = sqrt(r[j]- (v - x[j]) * (v - x[j])); se[sz].first = y[j] - d; se[sz].second = y[j] + d; ++sz; } sort(se, se + sz); for(i = 0; i < sz; ++i) { double nowl, nowr; nowl = se[i].first; nowr = se[i].second; for(j = i + 1; j < sz; ++j) { if(More(se[j].first, nowr)) { break; }else { if(More(se[j].second, nowr)) nowr = se[j].second; } } ret += nowr - nowl; i = j - 1; } return ret; } #define fs(x) ((x) < 0 ? (-(x)) : (x)) inline double rsimp(double l, double m, double r, double sl, double sm, double sr, double tot) { double m1 = (l + m) * 0.5, m2 = (m + r) * 0.5; double s0 = f(m1), s2 = f(m2); double gl = (sl + sm + s0 + s0 + s0 + s0) * (m - l), gr = (sm + sr + s2 + s2 + s2 + s2) * (r - m); if(fs(gl + gr - tot) < EPS) return gl + gr; return rsimp(l, m1, m, sl, s0, sm, gl) + rsimp(m, m2, r, sm, s2, sr, gr); } void deal() { int i, j = 0, k; for(i = 0; i < m; ++i) { s[i] = i; } sort(s, s + m, cmp0); for(i = 0; i < m; ++i){ for(k = 0; k < j; ++k) if(LessEqu((nx[k] - x[s[i]]) * (nx[k] - x[s[i]]) + (ny[k] - y[s[i]]) * (ny[k] - y[s[i]]) , (nr[k] - r[s[i]]) * (nr[k] - r[s[i]]))) break; if(k == j) { nx[j] = x[s[i]]; ny[j] = y[s[i]]; nr[j] = r[s[i]]; s[j] = j; j++; } } m = j; for(i = 0; i < m; ++i) { x[i] = nx[i], y[i] = ny[i], r[i] = nr[i]; } } void Round_S_Union() { sort(s, s + m, cmp1); double lo, hi, ans = 0.0; int i, j; for(i = 0; i < m; ++i) { xl[i] = x[s[i]] - r[s[i]], xr[i] = x[s[i]] + r[s[i]], r[s[i]] *= r[s[i]]; } for(i = 0; i < m; ++i) { double ilo, ihi; ilo = xl[i]; ihi = xr[i]; for(j = i + 1; j < m; ++j) { if(More(xl[j], ihi)) break; if(More(xr[j], ihi)) ihi = xr[j]; } double lo = ilo; double hi = ihi; L = i; R = j; double mid = (lo + hi) * 0.5; double sl = f(lo), sm = f(mid), sr = f(hi); double tot = sl + sr + sm + sm + sm + sm; ans += rsimp(lo, mid, hi, sl, sm, sr, tot); i = j - 1; } printf("%.2f\n", ans / 6.0); } int main() { int T, tcase = 1; scanf("%d", &T); while(T--) { scanf("%d%d", &n, &m); for(int i = 0; i < n; i++) { scanf("%d%d%d", &ps[i].x[0], &ps[i].x[1], &ps[i].k); ps[i].id = i; qs[i] = ps[i]; } Build_kdTree(0, n - 1, qs, 0); for(int i = 0; i < n; i++) { Query(0, n - 1, qs, ps[i]); Point req = q.top(); ps[i].dis = ps[i].distance(req); while(!q.empty()) { q.pop(); } } sort(ps, ps + n, cmp_dis); for(int i = 0; i < m; i++) { x[i] = ps[i].x[0]; y[i] = ps[i].x[1]; r[i] = sqrt(1.0 * ps[i].dis); } deal(); Round_S_Union(); } return 0; }