卧薪尝胆,厚积薄发。
CQOI2016 K远点对
Date: Sat Dec 15 21:49:22 CST 2018 In Category: NoCategory

Description:

给定 $n$ 个点,求欧几里得距离第 $k$ 远点对的距离平方。
$1\leqslant n\leqslant 10^5$

Solution:

先建出 $KDT$ ,然后维护一个堆,预先往堆中插入 $2k$ 个 $0$ ,然后每个点在 $KDT$ 上查距离最远点并不断更新这个堆即可,非常暴力。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<queue>
#include<vector>
#include<cctype>
#include<cstring>
using namespace std;
int n,m;
#define MAXN 100010
typedef long long ll;
priority_queue<ll,vector<ll>,greater<ll> > q;
struct node
{
int lc,rc;
int d[2],mx[2],mn[2];
int& operator [](int x){return d[x];}
}p[MAXN],t[MAXN];
int ptr = 0;
int newnode(){return ++ptr;}
int root;
int cmpd;
bool operator < (node a,node b){return a[cmpd] < b[cmpd];}
void updata(int rt)
{
for(int i = 0;i <= 1;++i)
{
if(t[rt].lc != 0)
{
t[rt].mn[i] = min(t[rt].mn[i],t[t[rt].lc].mn[i]);
t[rt].mx[i] = max(t[rt].mx[i],t[t[rt].lc].mx[i]);
}
if(t[rt].rc != 0)
{
t[rt].mn[i] = min(t[rt].mn[i],t[t[rt].rc].mn[i]);
t[rt].mx[i] = max(t[rt].mx[i],t[t[rt].rc].mx[i]);
}
}
return;
}
void build(int &rt,int l,int r,int type)
{
if(l > r)return;
rt = newnode();
int mid = ((l + r) >> 1);
cmpd = type;
nth_element(p + l,p + mid,p + r + 1);
t[rt] = p[mid];
for(int i = 0;i <= 1;++i)t[rt].mn[i] = t[rt].mx[i] = t[rt].d[i];
build(t[rt].lc,l,mid - 1,type ^ 1);
build(t[rt].rc,mid + 1,r,type ^ 1);
updata(rt);
return;
}
ll sqr(int x){return 1ll * x * x;}
ll dis(node a,node b){return sqr(a[0] - b[0]) + sqr(a[1] - b[1]);}
ll calc(node a,node b)
{
return max(sqr(a.mn[0] - b[0]),sqr(a.mx[0] - b[0])) + max(sqr(a.mn[1] - b[1]),sqr(a.mx[1] - b[1]));
}
#define INF 0x3f3f3f3f3f3f3f3f
void query(int rt,node k)
{
ll d,dl = -INF,dr = -INF;
d = dis(t[rt],k);
if(d > q.top()){q.pop();q.push(d);}
if(t[rt].lc)dl = calc(t[t[rt].lc],k);
if(t[rt].rc)dr = calc(t[t[rt].rc],k);
if(dl > dr)
{
if(dl > q.top())query(t[rt].lc,k);
if(dr > q.top())query(t[rt].rc,k);
}
else
{
if(dr > q.top())query(t[rt].rc,k);
if(dl > q.top())query(t[rt].lc,k);
}
return;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= 2 * m;++i)q.push(0);
for(int i = 1;i <= n;++i)
{
scanf("%d%d",&p[i][0],&p[i][1]);
}
build(root,1,n,0);
for(int i = 1;i <= n;++i)query(root,p[i]);
cout << q.top() << endl;
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡