luogu P1429 平面最近点对

传送门 

调半个晚上...一个板子整这么慢

之前网上一直没看明白 今天终于完事了

 

首先分治很容易想到 这里按x分

考虑暴力的复杂度极限 就是所有的点到中线距离相等

可以看出上下相距很远的点显然不对

那么这个很远是什么呢 是不是大于当前答案d的都可以舍去..

所以我们可以对于到中线的距离小于d的每个点找到与它y轴距离小于d的点更新答案(主要是因为画个圆太麻烦了)

然后这个可以证明每个点匹配的个数是常数 就需要用到网上流传的那个图了

至于为什么可以考虑如果一侧的d*d正方形里如果有四个以上的点那么最小值一定可以更小

 

代码真好写...

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<queue>
 6 #include<iostream>
 7 #define ms(a,b) memset(a,b,sizeof a)
 8 #define rep(i,a,n) for(int i = a;i <= n;i++)
 9 #define per(i,n,a) for(int i = n;i >= a;i--)
10 #define inf 2147483647
11 using namespace std;
12 typedef long long ll;
13 ll read() {
14     ll as = 0,fu = 1;
15     char c = getchar();
16     while(c < '0' || c > '9') {
17         if(c == '-') fu = -1;
18         c = getchar();
19     }
20     while(c >= '0' && c <= '9') {
21         as = as * 10 + c - '0';
22         c = getchar();
23     }
24     return as * fu;
25 }
26 const int N = 200003;
27 //head
28 typedef double D;
29 #define eps 1e-8
30 struct node {
31     D x,y;
32     D len() {return sqrt(x*x+y*y);}
33     node operator - (const node &o) const {
34         return (node){x-o.x,y-o.y};
35     }
36     bool operator < (const node &o) const {
37         return x < o.x;
38     }
39 }p[N];
40 int n;
41 
42 //[l,r)
43 D solve(int l,int r) {
44     if(r - l == 1) return 3e20;
45     int m = l+r >> 1;
46     D xmid = (p[m].x + p[m - 1].x) / 2.0;
47     D d = min(solve(l,m),solve(m,r));
48     int topb = 0,topc = 0;
49     static node a[N],b[N],c[N];
50     int L = l,R = m;
51     int curb = 0,curc = 0;
52     rep(i,l,r - 1) {
53         if(L < m && (R == r || p[L].y < p[R].y) ) {
54             a[i] = p[L++];
55             if(xmid - a[i].x < d) b[topb++] = a[i];
56         } else {
57             a[i] = p[R++];
58             if(a[i].x - xmid < d) c[topc++] = a[i];
59         }
60     }
61 
62     rep(i,l,r - 1) p[i] = a[i];
63     while(curb < topb || curc < topc) {
64         if(curb < topb && (curc == topc || b[curb].y < c[curc].y)) {
65             per(k,curc - 1,0) {
66                 if(b[curb].y - c[k].y > d) break;
67                 d = min(d,(c[k] - b[curb]).len());
68             }
69             curb++;
70         } else {
71             per(k,curb - 1,0) {
72                 if(c[curc].y - b[k].y > d) break;
73                 d = min(d,(b[k] - c[curc]).len());
74             }
75             curc++;
76         }
77     }
78     return d;
79 }
80 
81 int main() {
82     n = read();
83     rep(i,1,n) scanf("%lf%lf",&p[i].x,&p[i].y);
84     sort(p+1,p+n+1);
85     printf("%.4f\n",solve(1,n+1));
86     return 0;
87 }
posted @ 2018-11-28 20:03  白怀潇  阅读(189)  评论(0编辑  收藏  举报