#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <limits>
#include <iomanip>
using namespace std;
struct wynik //struktura wyniku (odleglosc,pozycje na wejsciu punktu 1 i 2)
{
double distance;
int p1;
int p2;
};
double odleglosc(pair<int,int> *a, pair<int,int> *b) //odleglosc pomiedzy dwoma punktami
{return sqrt((a->first-b->first)*(a->first-b->first)+(a->second-b->second)*(a->second-b->second));}
bool my_compare_X(pair<int,int> *a,pair<int,int> *b) //funktor greater dla OX
{return a->first==b->first?a->second<b->second:a->first<b->first;}
bool my_compare_Y(pair<int,int> *a,pair<int,int> *b) //funktor greater dla OY
{return a->second==b->second?a->first<b->first:a->second<b->second;}
//Globalne żeby były widoczne wewnątrz rekurencji bez kopiowania ani odkładania wskaźnika
vector<pair<int,int>>Punkty; //tablica punktów
vector<pair<int,int>*>X; //wektor ze wskaźnikami do punktów do sort po x
wynik *wyn=new wynik{numeric_limits<double>::max(),-1,-1};
void Filtruj(vector<pair<int,int>*>&Set,int p)
{
int s=0;
for(int i=0;i<Set.size();i++)
if(odleglosc(Set[i],new pair<int,int>(p,Set[i]->second))<=wyn->distance)Set[s++]=Set[i];
Set.resize(s);
}
void Najblizsze_punkty(int p,int k,vector<pair<int,int>*>Y)
{
if(k-p>1)
{
vector<pair<int,int>*>XL,XP; //wskazniki na zbiory lewy i prawy
int srodek=(k+p-1)/2; //X[srodek] jest osią podzialu
for(int i=0;i<Y.size();i++)
my_compare_X(X[srodek],Y[i])?XP.push_back(Y[i]):XL.push_back(Y[i]);
Najblizsze_punkty(p,srodek+1,XL); //czesc lewa
Najblizsze_punkty(srodek+1,k,XP); //czesc prawa
Filtruj(XL,X[srodek]->first); //usuwanie punktow odleglych dalej niz distance
Filtruj(XP,X[srodek]->first);
//przeglad punktow pomiedzy podzialami o odleglosci mniejszej niz distance
int p=0;
for(int i=0;i<XL.size();i++)
{
while(p<XP.size()-1&&XP[p+1]->second<XL[i]->second)p++;
int size=XP.size();
for(int x=max(0,p-2);x<=min(size-1,p+1);x++)
{
if(wyn->distance>odleglosc(XL[i],XP[x]))
{
wyn->distance=odleglosc(XL[i],XP[x]);
wyn->p1=min(int(XL[i]-&(Punkty[0])),int(XP[x]-&(Punkty[0])));
wyn->p2=max(int(XP[x]-&(Punkty[0])),int(XL[i]-&(Punkty[0])));
}
}
}
}
}
wynik* Algorytm()
{
vector<pair<int,int>*>Y; //wektor ze wskaźnikami do punktów do sort po y
for(int i=0;i<Punkty.size();i++)
{
X.push_back(&(Punkty[i])); //wrzuca wskaźniki do punktów z Punkty do X
Y.push_back(&(Punkty[i])); //wrzuca wskaźniki do punktów z Punkty do Y
}
sort(X.begin(),X.end(),my_compare_X); //sortuje punkty po wspolrzednej x
sort(Y.begin(),Y.end(),my_compare_Y); //sortuje punkty po wspolrzednej y
for(int i=1;i<X.size();i++) //jeśli są duplikaty to min odleglosc to 0
{
if(X[i]->first==X[i-1]->first && X[i]->second==X[i-1]->second) //czy duplikat
{
wyn->distance=0;
wyn->p1=min(int(X[i-1]-&(Punkty[0])),int(X[i]-&(Punkty[0])));
wyn->p2=max(int(X[i]-&(Punkty[0])),int(X[i-1]-&(Punkty[0])));
return wyn;
}
}
//glowny algorytm, bedziemy dzielili wzgledem prostych prostopadlych do OX
Najblizsze_punkty(0,Y.size(),Y);
return wyn; //zwracanie struktury wynikowej
}
int main()
{
int t,a,b;
cin>>t;
for(int i=0;i<t;i++)
{
cin>>a>>b;
Punkty.push_back({a,b});
}
wynik *W=Algorytm();
cout<<W->p1<<" "<<W->p2<<" "<<fixed<<setprecision(6)<<W->distance<<endl;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8YWxnb3JpdGhtPgojaW5jbHVkZSA8Y21hdGg+CiNpbmNsdWRlIDxsaW1pdHM+CiNpbmNsdWRlIDxpb21hbmlwPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKc3RydWN0IHd5bmlrIC8vc3RydWt0dXJhIHd5bmlrdSAob2RsZWdsb3NjLHBvenljamUgbmEgd2Vqc2NpdSBwdW5rdHUgMSBpIDIpCgl7Cglkb3VibGUgZGlzdGFuY2U7CglpbnQgcDE7CglpbnQgcDI7Cgl9OwoKZG91YmxlIG9kbGVnbG9zYyhwYWlyPGludCxpbnQ+ICphLCBwYWlyPGludCxpbnQ+ICpiKSAvL29kbGVnbG9zYyBwb21pZWR6eSBkd29tYSBwdW5rdGFtaQoJe3JldHVybiBzcXJ0KChhLT5maXJzdC1iLT5maXJzdCkqKGEtPmZpcnN0LWItPmZpcnN0KSsoYS0+c2Vjb25kLWItPnNlY29uZCkqKGEtPnNlY29uZC1iLT5zZWNvbmQpKTt9Cgpib29sIG15X2NvbXBhcmVfWChwYWlyPGludCxpbnQ+ICphLHBhaXI8aW50LGludD4gKmIpIC8vZnVua3RvciBncmVhdGVyIGRsYSBPWAoJe3JldHVybiBhLT5maXJzdD09Yi0+Zmlyc3Q/YS0+c2Vjb25kPGItPnNlY29uZDphLT5maXJzdDxiLT5maXJzdDt9Cgpib29sIG15X2NvbXBhcmVfWShwYWlyPGludCxpbnQ+ICphLHBhaXI8aW50LGludD4gKmIpIC8vZnVua3RvciBncmVhdGVyIGRsYSBPWQoJe3JldHVybiBhLT5zZWNvbmQ9PWItPnNlY29uZD9hLT5maXJzdDxiLT5maXJzdDphLT5zZWNvbmQ8Yi0+c2Vjb25kO30KCQovL0dsb2JhbG5lIMW8ZWJ5IGJ5xYJ5IHdpZG9jem5lIHdld27EhXRyeiByZWt1cmVuY2ppIGJleiBrb3Bpb3dhbmlhIGFuaSBvZGvFgmFkYW5pYSB3c2thxbpuaWthCnZlY3RvcjxwYWlyPGludCxpbnQ+PlB1bmt0eTsgLy90YWJsaWNhIHB1bmt0w7N3CnZlY3RvcjxwYWlyPGludCxpbnQ+Kj5YOyAvL3dla3RvciB6ZSB3c2thxbpuaWthbWkgZG8gcHVua3TDs3cgZG8gc29ydCBwbyB4Cnd5bmlrICp3eW49bmV3IHd5bmlre251bWVyaWNfbGltaXRzPGRvdWJsZT46Om1heCgpLC0xLC0xfTsKCnZvaWQgRmlsdHJ1aih2ZWN0b3I8cGFpcjxpbnQsaW50Pio+JlNldCxpbnQgcCkKCXsKCWludCBzPTA7Cglmb3IoaW50IGk9MDtpPFNldC5zaXplKCk7aSsrKQoJCWlmKG9kbGVnbG9zYyhTZXRbaV0sbmV3IHBhaXI8aW50LGludD4ocCxTZXRbaV0tPnNlY29uZCkpPD13eW4tPmRpc3RhbmNlKVNldFtzKytdPVNldFtpXTsKCVNldC5yZXNpemUocyk7Cgl9Cgp2b2lkIE5hamJsaXpzemVfcHVua3R5KGludCBwLGludCBrLHZlY3RvcjxwYWlyPGludCxpbnQ+Kj5ZKQoJewoJaWYoay1wPjEpCgkJewoJCXZlY3RvcjxwYWlyPGludCxpbnQ+Kj5YTCxYUDsgLy93c2them5pa2kgbmEgemJpb3J5IGxld3kgaSBwcmF3eQoJCWludCBzcm9kZWs9KGsrcC0xKS8yOyAvL1hbc3JvZGVrXSBqZXN0IG9zacSFIHBvZHppYWx1CgkJZm9yKGludCBpPTA7aTxZLnNpemUoKTtpKyspCgkJCW15X2NvbXBhcmVfWChYW3Nyb2Rla10sWVtpXSk/WFAucHVzaF9iYWNrKFlbaV0pOlhMLnB1c2hfYmFjayhZW2ldKTsKCgkJTmFqYmxpenN6ZV9wdW5rdHkocCxzcm9kZWsrMSxYTCk7IC8vY3plc2MgbGV3YQoJCU5hamJsaXpzemVfcHVua3R5KHNyb2RlaysxLGssWFApOyAvL2N6ZXNjIHByYXdhCgkJRmlsdHJ1aihYTCxYW3Nyb2Rla10tPmZpcnN0KTsJLy91c3V3YW5pZSBwdW5rdG93IG9kbGVnbHljaCBkYWxlaiBuaXogZGlzdGFuY2UKCQlGaWx0cnVqKFhQLFhbc3JvZGVrXS0+Zmlyc3QpOwoJCS8vcHJ6ZWdsYWQgcHVua3RvdyBwb21pZWR6eSBwb2R6aWFsYW1pIG8gb2RsZWdsb3NjaSBtbmllanN6ZWogbml6IGRpc3RhbmNlCgkJCgkJaW50IHA9MDsKCQlmb3IoaW50IGk9MDtpPFhMLnNpemUoKTtpKyspCgkJCXsKCQkJd2hpbGUocDxYUC5zaXplKCktMSYmWFBbcCsxXS0+c2Vjb25kPFhMW2ldLT5zZWNvbmQpcCsrOwoJCQlpbnQgc2l6ZT1YUC5zaXplKCk7CgkJCWZvcihpbnQgeD1tYXgoMCxwLTIpO3g8PW1pbihzaXplLTEscCsxKTt4KyspCgkJCQl7CgkJCQlpZih3eW4tPmRpc3RhbmNlPm9kbGVnbG9zYyhYTFtpXSxYUFt4XSkpCgkJCQkJewoJCQkJCXd5bi0+ZGlzdGFuY2U9b2RsZWdsb3NjKFhMW2ldLFhQW3hdKTsKCQkJCQl3eW4tPnAxPW1pbihpbnQoWExbaV0tJihQdW5rdHlbMF0pKSxpbnQoWFBbeF0tJihQdW5rdHlbMF0pKSk7CgkJCQkJd3luLT5wMj1tYXgoaW50KFhQW3hdLSYoUHVua3R5WzBdKSksaW50KFhMW2ldLSYoUHVua3R5WzBdKSkpOwoJCQkJCX0KCQkJCX0KCQkJfQoJCX0KCX0KCnd5bmlrKiBBbGdvcnl0bSgpCgl7Cgl2ZWN0b3I8cGFpcjxpbnQsaW50Pio+WTsgLy93ZWt0b3IgemUgd3NrYcW6bmlrYW1pIGRvIHB1bmt0w7N3IGRvIHNvcnQgcG8geQoJCglmb3IoaW50IGk9MDtpPFB1bmt0eS5zaXplKCk7aSsrKQoJCXsKCQlYLnB1c2hfYmFjaygmKFB1bmt0eVtpXSkpOyAvL3dyenVjYSB3c2thxbpuaWtpIGRvIHB1bmt0w7N3IHogUHVua3R5IGRvIFgKCQlZLnB1c2hfYmFjaygmKFB1bmt0eVtpXSkpOyAvL3dyenVjYSB3c2thxbpuaWtpIGRvIHB1bmt0w7N3IHogUHVua3R5IGRvIFkKCQl9CgkJCglzb3J0KFguYmVnaW4oKSxYLmVuZCgpLG15X2NvbXBhcmVfWCk7IC8vc29ydHVqZSBwdW5rdHkgcG8gd3Nwb2xyemVkbmVqIHgKCXNvcnQoWS5iZWdpbigpLFkuZW5kKCksbXlfY29tcGFyZV9ZKTsgLy9zb3J0dWplIHB1bmt0eSBwbyB3c3BvbHJ6ZWRuZWogeQoJCglmb3IoaW50IGk9MTtpPFguc2l6ZSgpO2krKykgLy9qZcWbbGkgc8SFIGR1cGxpa2F0eSB0byBtaW4gb2RsZWdsb3NjIHRvIDAKCQl7CgkJaWYoWFtpXS0+Zmlyc3Q9PVhbaS0xXS0+Zmlyc3QgJiYgWFtpXS0+c2Vjb25kPT1YW2ktMV0tPnNlY29uZCkgLy9jenkgZHVwbGlrYXQKCQkJewoJCQl3eW4tPmRpc3RhbmNlPTA7CgkJCXd5bi0+cDE9bWluKGludChYW2ktMV0tJihQdW5rdHlbMF0pKSxpbnQoWFtpXS0mKFB1bmt0eVswXSkpKTsKCQkJd3luLT5wMj1tYXgoaW50KFhbaV0tJihQdW5rdHlbMF0pKSxpbnQoWFtpLTFdLSYoUHVua3R5WzBdKSkpOwoJCQlyZXR1cm4gd3luOwoJCQl9CgkJfQoJLy9nbG93bnkgYWxnb3J5dG0sIGJlZHppZW15IGR6aWVsaWxpIHd6Z2xlZGVtIHByb3N0eWNoIHByb3N0b3BhZGx5Y2ggZG8gT1gKCU5hamJsaXpzemVfcHVua3R5KDAsWS5zaXplKCksWSk7CgkJCglyZXR1cm4gd3luOyAvL3p3cmFjYW5pZSBzdHJ1a3R1cnkgd3luaWtvd2VqCgl9CgkKaW50IG1haW4oKSAKCXsKCWludCB0LGEsYjsKCWNpbj4+dDsKCWZvcihpbnQgaT0wO2k8dDtpKyspCgkJewoJCWNpbj4+YT4+YjsKCQlQdW5rdHkucHVzaF9iYWNrKHthLGJ9KTsKCQl9Cgl3eW5payAqVz1BbGdvcnl0bSgpOwoJY291dDw8Vy0+cDE8PCIgIjw8Vy0+cDI8PCIgIjw8Zml4ZWQ8PHNldHByZWNpc2lvbig2KTw8Vy0+ZGlzdGFuY2U8PGVuZGw7Cgl9