1. 程式人生 > >BZOJ2458: [BeiJing2011]最小三角形

BZOJ2458: [BeiJing2011]最小三角形

hup ret beijing line str lse con [1] urn

BZOJ2458: [BeiJing2011]最小三角形

https://lydsy.com/JudgeOnline/problem.php?id=2458

分析:

  • 求最近點次近點更新答案能A掉這道題,雖然我不知道是不是正確的。
  • 那麽用\(KDtree\)亂搞即可。

代碼:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <iostream>
using namespace std;
typedef long long ll;
typedef double f2;
#define N 200050
#define db(x) cerr<<#x<<" = "<<x<<endl
#define ls ch[p][0]
#define rs ch[p][1]
int now;
struct Point {
    ll p[2];
    Point() {p[0]=p[1]=0;}
    Point(ll x_,ll y_) {p[0]=x_,p[1]=y_;}
    bool operator < (const Point &u) const {
        return p[now]==u.p[now] ? p[!now] < u.p[!now] : p[now] < u.p[now];
    }
}a[N];
int n,ch[N][2],mx[N][2],mn[N][2],root;
void pushup(int p,int x) {
    mn[p][0]=min(mn[p][0],mn[x][0]);
    mn[p][1]=min(mn[p][1],mn[x][1]);
    mx[p][0]=max(mx[p][0],mx[x][0]);
    mx[p][1]=max(mx[p][1],mx[x][1]);
}
int build(int l,int r,int flg) {
    int mid=(l+r)>>1,p=mid;
    now=flg;
    nth_element(a+l,a+mid,a+r+1);
    mx[p][0]=mn[p][0]=a[p].p[0];
    mx[p][1]=mn[p][1]=a[p].p[1];
    if(l<mid) ls=build(l,mid-1,flg^1),pushup(p,ls);
    if(r>mid) rs=build(mid+1,r,flg^1),pushup(p,rs);
    return p;
}
int p1,p2;
ll s1,s2;
ll pf(ll x) {return x*x;}
ll calc(const Point &p1,const Point &p2) {return pf(p1.p[0]-p2.p[0])+pf(p1.p[1]-p2.p[1]);}
ll F(int x,int p) {
    if(a[p].p[0]>=mn[x][0]&&a[p].p[0]<=mx[x][0]&&a[p].p[1]>=mn[x][1]&&a[p].p[1]<=mx[x][1]) return 0;
    if(a[p].p[0]>=mn[x][0]&&a[p].p[0]<=mx[x][0]) {
        return min(pf(mn[x][1]-a[p].p[1]),pf(mx[x][1]-a[p].p[1]));
    }
    if(a[p].p[1]>=mn[x][1]&&a[p].p[1]<=mx[x][1]) {
        return min(pf(mn[x][0]-a[p].p[0]),pf(mx[x][0]-a[p].p[0]));
    }
    return min(calc(a[p],Point(mn[x][0],mn[x][1])),min(calc(a[p],Point(mn[x][0],mx[x][1])),min(calc(a[p],Point(mx[x][0],mn[x][1])),calc(a[p],Point(mx[x][0],mx[x][1])))));
}
void query(int p,int id) {
    ll t=calc(a[p],a[id]);
    if(p!=id&&(!p1||t<s1)) {
        s1=t; p1=p;
    }
    ll dls=ls?F(ls,id):1ll<<62;
    ll drs=rs?F(rs,id):1ll<<62;
    if(dls<drs) {
        if(dls<s1) query(ls,id);
        if(drs<s1) query(rs,id);
    }else {
        if(drs<s1) query(rs,id);
        if(dls<s1) query(ls,id);
    }
}
void query2(int p,int id) {
    ll t=calc(a[p],a[id]);
    if(p!=id&&p!=p1&&(!p2||t<s2)) {
        s2=t; p2=p;
    }
    ll dls=ls?F(ls,id):1ll<<62;
    ll drs=rs?F(rs,id):1ll<<62;
    if(dls<drs) {
        if(dls<s2) query2(ls,id);
        if(drs<s2) query2(rs,id);
    }else {
        if(drs<s2) query2(rs,id);
        if(dls<s2) query2(ls,id);
    }
}
int main() {
    scanf("%d",&n);
    int i;
    for(i=1;i<=n;i++) scanf("%lld%lld",&a[i].p[0],&a[i].p[1]);
    root=build(1,n,0);
    f2 ans=1e10;
    for(i=1;i<=n;i++) {
        p1=p2=0; s1=s2=1ll<<62;
        query(root,i);
        query2(root,i);
        ans=min(ans,sqrt(s1)+sqrt(s2)+sqrt(calc(a[p1],a[p2])));
    }
    printf("%.6f\n",ans);
}

BZOJ2458: [BeiJing2011]最小三角形