BZOJ2458: [BeiJing2011]最小三角形
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);
}