链接:戳这里
Palace
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
问题描述
为了寻找失去的爱人Cupid,Psyche需要完成Venus的最后一项任务:前往冥界,收集一盒冥界皇后Prosperina的美貌。
冥界有 n个神殿,可以表示为平面上的 n个整点。Psyche想要找到这 n座神殿中,最近的两座神殿之间的距离。传说那就是通往主殿的密码。
但是冥界神秘莫测,在不同的时刻,这 n 座神殿中的某一座会消失。
Psyche想要知道,对于 n 座神殿中的任意一座消失的情况,最近的两座神殿之间的距离。你只需要输出它们的和。
为避免精度误差,定义两点 (x1 ,y1 ),(x2 ,y2 )间的距离为 d=(x1 −x2)^2 +(y1 −y2 )^2 。
输入描述
第一行,一个整数 T (1≤T≤5),代表数据组数。
对于每组数据,第一行,一个整数 n (3≤n≤10e5),代表神殿个数。
下面 n 行,每行两个整数 x, y (−10e5≤x,y≤10e5),代表神殿的位置在 (x,y)。
注意可能存在两座神殿坐落在同一位置。
输出描述
输出 T 行,对于每组数据,输出 n 座神殿中的任意一座消失的情况,最近两座神殿之间的距离的和。
输入样例
1
3
0 0
1 1
2 2
输出样例
12
Hint
神殿 (0,0)消失时, d=(1−2)^2 +(1−2)^2 =2;
神殿 (1,1)消失时, d=(0−2)^2+(0−2)^2 =8;
神殿 (2,2)消失时, d = (0-1) ^ 2 + (0-1) ^ 2 = 2
故答案为 2 + 8 + 2 = 12。
思路:
最近的那对点对可以贡献n-2次,然后就是分别删掉两点中的一点算贡献
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include <ctime>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<iomanip>
#include<cmath>
#define mst(ss,b) memset((ss),(b),sizeof(ss))
#define maxn 0x3f3f3f3f
#define MAX 1000100
///#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef unsigned long long ull;
#define INF (1ll<<60)-1
using namespace std;
struct point{
ll x,y;
bool operator <(const point &a)const{
if(x==a.x) return y<a.y;
return x<a.x;
}
}s[100100];
typedef pair<ll ,pair<int,int> > Pair;
Pair calc(int i,int j){
ll ans=(s[i].x-s[j].x)*(s[i].x-s[j].x)+(s[i].y-s[j].y)*(s[i].y-s[j].y);
return make_pair(ans,make_pair(i,j));
}
int p[100100];
bool cmpy(int a,int b){
return s[a].y<s[b].y;
}
Pair Dis(int l,int r){
Pair tmp;
if(l+1==r) return calc(l,r);
if(l+2==r){
Pair t1=calc(l,r);
Pair t2=calc(l,l+1);
Pair t3=calc(l+1,r);
tmp=min(t1,min(t2,t3));
return tmp;
}
int mid=(l+r)/2;
Pair d1=Dis(l,mid);
Pair d2=Dis(mid+1,r);
tmp=min(d1,d2);
int cnt=0;
for(int i=l;i<=r;i++){
if((s[mid].x-s[i].x)*(s[mid].x-s[i].x)<tmp.first) p[cnt++]=i;
}
sort(p,p+cnt,cmpy);
for(int i=0;i<cnt;i++){
for(int j=i+1;j<cnt;j++){
int u=p[i],v=p[j];
if((s[v].y-s[u].y)*(s[v].y-s[u].y)>tmp.first) break;
Pair d3=calc(u,v);
tmp=min(tmp,d3);
}
}
return tmp;
}
int main(){
int T,n;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%I64d%I64d",&s[i].x,&s[i].y);
sort(s,s+n);
Pair d=Dis(0,n-1);
ll ans=d.first*(n-2);
swap(s[d.second.first],s[n-1]);
ans+=Dis(0,n-2).first;
swap(s[d.second.first],s[n-1]);
swap(s[d.second.second],s[n-1]);
ans+=Dis(0,n-2).first;
printf("%I64d\n",ans);
}
return 0;
}