不要学我的KD-Tree,很不标准,只是不知道为什么把题水过了。
话说这个BZOJ真的不行啊,怀疑跟少主家是一样的评测机,哼~。
题意
已知平面内 N 个点的坐标,求欧氏距离下的第 K 远点对。
k<=100
分析
既然答案只有一个的话。。。
我想的话是二分猜+KD-tree
时间复杂度大概是60*n*n^1/2
等等。。。K怎么这么小
比K大的就搜索,否则不搜索。。。
优先队列吧
如果按照加点的话很可能不平衡,因此不如先加进去。自己这个点应该不会造成影响,出题人良心(大拇指
可是会有重复点啊,那么我们维护大小为2k的?应该可行
最后我们的点按照横坐标排序,然后最左,最右这种操作来搜索。
哇哈哈哈,试试
注意开LL
时间复杂度大概就是n^3/2这个级别的吧
.
.
.
.
.
.
.
事实证明我yy的那个左右加点的操作是把时间拖慢了,KDtree本来自带一个排序嘛。。。
(还有其实这根本不是我认真写的思路,是我写给自己看的思考过程而已啦哈哈哈哈)
代码
先写几个KDtree注意的点
1、mx和mi两个在估价的时候同时要用,不要以为找最大值就不用mi了,可能负数呢,所以不要忘了abs。
2、D那个排序的全局变量只能放在结构体外面,因为结构体内部的东西不一定被定义了的。
3、特别注意估价函数以及查询的写法,KD-tree的核心了吧。
using namespace std;
typedef long long LL;
const int maxn=2e5+1000,inf=2147483647;
struct Point{
int d[2];
friend bool operator<(Point a,Point b)
{
return a.d[0]!=b.d[0]?a.d[0]<b.d[0]:a.d[1]<b.d[1];
}
void ins()
{
scanf("%d%d",&d[0],&d[1]);
}
}p[maxn];
struct mycmp
{
bool operator()(LL a,LL b)
{
return a>b;
}
};
priority_queue<LL,vector<LL>,mycmp>pq;
int D;
bool cmp(Point a,Point b)
{
return a.d[D]<b.d[D];
}
int n,k;
struct KD_Tree
{
static const int K=2;
int np,rt;
struct data
{
int mi[K],mx[K],ch[2];
}T[maxn];
void Intial()
{
np=rt=0;
memset(T,0,sizeof(T));
}
void pushup(int now)
{
for(int i=0;i<K;i++)
{
T[now].mi[i]=inf,T[now].mx[i]=0;
for(int j=0;j<2;j++)
{
if(T[now].ch[j])
{
T[now].mi[i]=min(T[now].mi[i],T[T[now].ch[j]].mi[i]);
T[now].mx[i]=max(T[now].mx[i],T[T[now].ch[j]].mx[i]);
}
}
}
}
void Build(int &now,int L,int R,int k)
{
now=++np;
int m=(L+R)>>1;
if(L==R)
{
for(int i=0;i<K;i++)
T[now].mx[i]=T[now].mi[i]=p[L].d[i];
return;
}
D=k;nth_element(p+L,p+m+1,p+R+1,cmp);
Build(T[now].ch[0],L,m,(k+1)%K);
Build(T[now].ch[1],m+1,R,(k+1)%K);
pushup(now);
}
LL Dist(data a,Point b)
{
LL ret=0;
int t;
for(int i=0;i<K;i++)
t=max( abs(a.mx[i]-b.d[i]) , abs(a.mi[i]-b.d[i]) ),ret+=1ll*t*t;
return ret;
}
void query(int now,int L,int R,Point a)
{
if(L==R)
{
LL d=Dist(T[now],a);
if(pq.size()<2*k)pq.push(d);
else if(d>pq.top())pq.pop(),pq.push(d);
return;
}
int m=(L+R)>>1;
LL d1=Dist(T[T[now].ch[0]],a),d2=Dist(T[T[now].ch[1]],a);
if(d1>d2)
{
if(pq.size()<2*k || d1>pq.top())query(T[now].ch[0],L,m,a);
if(pq.size()<2*k || d2>pq.top())query(T[now].ch[1],m+1,R,a);
}
else
{
if(pq.size()<2*k || d2>pq.top())query(T[now].ch[1],m+1,R,a);
if(pq.size()<2*k || d1>pq.top())query(T[now].ch[0],L,m,a);
}
}
}kdt;
void Init()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)p[i].ins();//,pp[i]=p[i];
kdt.Build(kdt.rt,1,n,0);
}
void solve()
{
/*sort(pp+1,pp+n+1);
for(int i=1,j=n;i<=j;i++,j--)
{
kdt.query(kdt.rt,1,n,pp[i]);
if(i!=j)kdt.query(kdt.rt,1,n,pp[j]);
}*/
for(int i=1;i<=n;i++)
kdt.query(kdt.rt,1,n,p[i]);
//printf("%lld\n",pq.top());
cout<<pq.top()<<endl;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out1.txt","w",stdout);
Init();
solve();
return 0;
}