题意:给出$N$个点,求其中周长最小的三角形(共线的也计算在内)。$N \leq 2 \times 10^5$
这道题唤起了我对平面最近点对的依稀记忆
考虑平面最近点对的分治,将分界线两边的求解改为求三角形的最小边长即可。
小心坐标乘积爆int
不难但就是想不出
//This code is written by Itst #include<bits/stdc++.h> #define int long long #define ld long double #define eps (ld)1e-10 using namespace std; inline int read(){ ; ; char c = getchar(); while(c != EOF && !isdigit(c)){ if(c == '-') f = ; c = getchar(); } while(c != EOF && isdigit(c)){ a = (a << ) + (a << ) + (c ^ '); c = getchar(); } return f ? -a : a; } ; struct node{ int x , y; }now[MAXN] , pot[MAXN]; int N; ld dis(node a , node b){ return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } ld len(node a , node b , node c){ return dis(a , b) + dis(b , c) + dis(a , c); } bool cmp1(node a , node b){ return a.y < b.y; } ld solve(int l , int r){ ){ ld minN = 0x3f3f3f3f; for(int i = l ; i <= r ; i++) ; j <= r ; j++) ; k <= r ; k++) minN = min(minN , len(now[i] , now[j] , now[k])); return minN; } ; ld k = (now[mid].x + now[mid + ].x) * (ld) , r) , d = min(d1 , d2); sort(now + l , now + r + , cmp1); ; for(int i = l ; i <= r ; i++) if(fabs(now[i].x - k) + eps < d) pot[++p] = now[i]; ; i <= p ; i++) ; j <= p && pot[j].y - pot[i].y + eps < d ; j++) ; k <= p && pot[k].y - pot[i].y + eps < d ; k++) d = min(d , len(pot[i] , pot[j] , pot[k])); return d; } bool cmp(node a , node b){ return a.x < b.x; } signed main(){ #ifdef LG freopen("4423.in" , "r" , stdin); //freopen("4423.out" , "w" , stdout); #endif N = read(); ; i <= N ; i++){ now[i].x = read(); now[i].y = read(); } sort(now + , now + N + , cmp); cout << ) << solve( , N); ; }