「LuoguP1429」 平面最近點對(加強版)
阿新 • • 發佈:2018-10-20
urn dig tchar return article ron sdi nbsp git
題目描述
給定平面上n個點,找出其中的一對點的距離,使得在這n個點的所有點對中,該距離為所有點對中最小的
輸入輸出格式
輸入格式:第一行:n;2≤n≤200000
接下來n行:每行兩個實數:x y,表示一個點的行坐標和列坐標,中間用一個空格隔開。
輸出格式:僅一行,一個實數,表示最短距離,精確到小數點後面4位。
輸入輸出樣例
輸入樣例#1: 復制3 1 1 1 2 2 2輸出樣例#1: 復制
1.0000
說明
0<=x,y<=10^9
題解
考場清晰的記得以前聽過,並且記錯做法還覺得自己是天才......
考場思路:按橫軸排序,然後從左往右枚舉每個點,把和該點的橫坐標之差小於$ans$的點暴力算。
然後怕構造數據被卡(很多個點的橫坐標差不多,豎軸差很多的話可以卡成$N$方),於是考慮用權值線段樹優化豎軸,也就是從權值線段樹中取豎軸在當前點加減ans範圍的點暴力算。(考試$x,y$範圍1e6)
這樣應該就不會T了......
然後毒瘤評測人只給64M啊!哪裏夠開權值線段樹啊!
於是把掃描線轉了45°(也可以理解為把紙轉45°),再做類暴力,這樣就不好卡了。
然後就過了2333
1 /* 2 qwerta 3 P1429 平面最近點對(加強版) 4 Accepted 5 100 6 代碼 C++,1.16KB7 提交時間 2018-10-19 15:55:35 8 耗時/內存 9 348ms, 2064KB 10 */ 11 #include<algorithm> 12 #include<iostream> 13 #include<cstdio> 14 #include<cmath> 15 using namespace std; 16 #define R register 17 inline int read() 18 { 19 char ch=getchar(); 20 int x=0;21 while(!isdigit(ch))ch=getchar(); 22 while(isdigit(ch)){x=x*10+ch-‘0‘;ch=getchar();} 23 return x; 24 } 25 const int MAXN=200000+3,MAXX=1000000+3; 26 struct emm{ 27 int x,y; 28 }a[MAXN]; 29 const double k=-0.5; 30 bool cmp(emm qaq,emm qwq) 31 { 32 return qaq.y-k*qaq.x<qwq.y-k*qwq.x; 33 } 34 inline double dis(int u,int v) 35 { 36 return sqrt(1LL*(a[u].x-a[v].x)*(a[u].x-a[v].x)+1LL*(a[u].y-a[v].y)*(a[u].y-a[v].y)); 37 } 38 double gen2=sqrt(2); 39 inline double je(int u,int v) 40 { 41 return abs(((a[u].y-k*a[u].x)-(a[v].y-k*a[v].x)))/gen2; 42 } 43 int main() 44 { 45 //freopen("dark.in","r",stdin); 46 //freopen("dark.out","w",stdout); 47 int n=read(); 48 for(R int i=1;i<=n;++i) 49 a[i].x=read(),a[i].y=read(); 50 sort(a+1,a+n+1,cmp); 51 int l=1,r=1; 52 double ans=dis(1,2); 53 for(R int u=1;u<=n;++u) 54 { 55 while(je(u,l)>ans)++l; 56 while(je(r+1,u)<ans&&r<n)++r; 57 //cout<<u<<" "<<l<<" "<<r<<endl; 58 for(R int v=l;v<=r;++v) 59 if(u!=v) 60 ans=min(ans,dis(u,v)); 61 } 62 printf("%.4f",ans); 63 return 0; 64 }
「LuoguP1429」 平面最近點對(加強版)