Time Limit: 30 Sec  Memory Limit: 512 MB

Submit: 588  Solved: 309

[Submit][Status][Discuss]

Description

已知平面内 N 个点的坐标,求欧氏距离下的第 K 远点对。

Input

输入文件第一行为用空格隔开的两个整数 N, K。接下来 N 行,每行两个整数 X,Y,表示一个点
的坐标。1 < =  N < =  100000, 1 < =  K < =  100, K < =  N*(N−1)/2 , 0 < =  X, Y < 2^31。

Output

输出文件第一行为一个整数,表示第 K 远点对的距离的平方(一定是个整数)。

Sample Input

10 5

0 0

0 1

1 0

1 1

2 0

2 1

1 2

0 2

3 0

3 1

Sample Output

9

【题解】

第K远点对。是说C(N,2)个点对里面。点对之间的距离是第K远的。求这个距离。

我们枚举每个点。然后查看它与其他点的距离。

维护一个1..2*K远的队列。然后不断更新这个队列

(为什么是2*k,想想我们在枚举第一个点的时候,假如和第3个点配对,距离为第2远那么下次再枚举第3个点的时候还会遇到第一个点。又出现了一个第2远的数要加入到队列中。而这两个距离其实是同一个点对的。即排列。考虑其他第1,3,4,..k远的点对也会出现这种情况。我们就把K变成2*K。);

【代码】

#include <cstdio>
#include <algorithm> using namespace std; const int MAX_N = 109000; int n, k,root,now;
long long duilie[300]; struct point
{
long long d[2], mi_n[2], ma_x[2] ;
int l,r;
}; point t[MAX_N],op; void input_data()
{
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++)
scanf("%lld%lld", &t[i].d[0], &t[i].d[1]);
} bool cmp(point a, point b)
{
return a.d[now] < b.d[now];
} void up_data(int rt)
{
int l = t[rt].l, r = t[rt].r;
for (int i = 0; i <= 1; i++)
{
if (l)
{
t[rt].ma_x[i] = max(t[rt].ma_x[i], t[l].ma_x[i]);
t[rt].mi_n[i] = min(t[rt].mi_n[i], t[l].mi_n[i]);
}
if (r)
{
t[rt].ma_x[i] = max(t[rt].ma_x[i], t[r].ma_x[i]);
t[rt].mi_n[i] = min(t[rt].mi_n[i], t[r].mi_n[i]);
}
}
} int build(int begin, int end, int fx)
{
int m = (begin + end) >> 1;
now = fx;
nth_element(t + begin, t + m, t + end + 1, cmp);
for (int i = 0; i <= 1; i++)
t[m].ma_x[i] = t[m].mi_n[i] = t[m].d[i];
if (begin < m)
t[m].l = build(begin, m - 1, 1 - fx);
if (m < end)
t[m].r = build(m + 1, end, 1 - fx);
up_data(m);
return m;
} long long sqr(long long x)
{
return x*x;
} long long get_dis(int rt)
{
return sqr(t[rt].d[0] - op.d[0]) + sqr(t[rt].d[1] - op.d[1]);
} long long gujia(int rt)//估价函数
{
long long temp = 0;
for (int i = 0; i <= 1; i++)
temp += max(sqr(t[rt].mi_n[i] - op.d[i]), sqr(t[rt].ma_x[i] - op.d[i]));
return temp;
} void query(int rt)
{
long long dis = get_dis(rt);
int k_th = k;
while (duilie[k_th] <= dis)//找到这个距离在队列中的合适位置。
{
k_th--;
if (!k_th)
break;
}
if (k_th != k)
{
for (int i = k; i >= k_th + 2; i--)
duilie[i] = duilie[i - 1];//这个位置后面的数字往后挪。
duilie[k_th + 1] = dis;
}
int l = t[rt].l, r = t[rt].r;
long long gl = -1,gr = -1;
if (l)
gl = gujia(l);
if (r)
gr = gujia(r);
if (gl < gr)
{
if (gr >= duilie[k])
query(r);
if (gl >= duilie[k])
query(l);
}
else
{
if (gl >= duilie[k])
query(l);
if (gr >= duilie[k])
query(r);
}
} void get_ans()
{
root = build(1, n, 0);
k = k * 2;//直接求2*k远
for (int i = 1; i <= k; i++)//duilie[1..k]分别表示第1,2,3..远。因此它是递减队列。
duilie[i] = 0;
for (int i = 1; i <= n; i++)
{
op.d[0] = t[i].d[0], op.d[1] = t[i].d[1];
query(root);
}
} void output_ans()
{
printf("%lld\n", duilie[k]);
} int main()
{
//freopen("F:\\rush.txt", "r", stdin);
input_data();
get_ans();
output_ans();
return 0;
}

【52.55%】【BZOJ 4520】K远点对的更多相关文章

  1. BZOJ - 4520 K远点对

    题意:已知平面内 N 个点的坐标,求欧氏距离下的第 K 远点对 维护大小为2k最小堆,KD树的估值用前面提到的做法 PS.网上有人估价是使用边界四个点的最值来独立枚举,然而这样写似乎过不了 #incl ...

  2. BZOJ 4520: [Cqoi2016]K远点对

    4520: [Cqoi2016]K远点对 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 638  Solved: 340[Submit][Status ...

  3. BZOJ 4520 [Cqoi2016]K远点对(KD树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4520 [题目大意] 求K远点对距离 [题解] 修改估价函数为欧式上界估价,对每个点进行 ...

  4. BZOJ 4520: [Cqoi2016]K远点对(k-d tree)

    Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 1162  Solved: 618[Submit][Status][Discuss] Descripti ...

  5. BZOJ 4520: [Cqoi2016]K远点对 KDtree + 估价函数 + 堆

    Code: #include<bits/stdc++.h> #define ll long long #define maxn 200000 #define inf 10000000000 ...

  6. [Cqoi2016]K远点对 K-Dtree

    4520: [Cqoi2016]K远点对 链接 bzoj 思路 用K-Dtree求点的最远距离. 求的时候顺便维护一个大小为2k的小根堆. 不知道为啥一定会对. 代码 #include <bit ...

  7. 【BZOJ-4520】K远点对 KD-Tree + 堆

    4520: [Cqoi2016]K远点对 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 490  Solved: 237[Submit][Status ...

  8. 【bzoj4520】 Cqoi2016—K远点对

    http://www.lydsy.com/JudgeOnline/problem.php?id=4520 (题目链接) 题意 求平面内第K远点对的距离. Solution 左转题解:jump 细节 刚 ...

  9. 【BZOJ4520】K远点对(KD-Tree)

    [BZOJ4520]K远点对(KD-Tree) 题面 BZOJ 洛谷 题解 考虑暴力. 维护一个大小为\(K\)的小根堆,然后每次把两个点之间的距离插进去,然后弹出堆顶 这样子可以用\(KD-Tree ...

随机推荐

  1. 仿Google Nexus菜单样式

    在线演示 本地下载

  2. python 类的创建

  3. 元素的高度(基于vue)

    const viewH =el.target.offsetHeight;//可见高度 const contentH =el.target.scrollHeight;//内容高度 const scrol ...

  4. hdu4318 最短路变形

    和hdu有一题差不多.给的是损失比,1-c%就是保存了多少,找出最大的保存率即可. #include<stdio.h> #include<iostream> #include& ...

  5. sqlplus连接数据库报错SP2-0642: SQL*Plus internal error state 2130, context 0:0:0解决

    sqlplus连接数据库报错SP2-0642: SQL*Plus internal error state 2130, context 0:0:0解决 sqlplus 连接数据库报错SP2-0642: ...

  6. iOS用同一个工程创建两个不同版本的应用

    http://www.cocoachina.com/ios/20150916/13324.html 如果同一个应用, 需要做一个带广告Lite版本, 一个不带广告的Pro版本. 那么问题来了, 该如何 ...

  7. PHPExcel 去掉错误提示 保护表格

    $objPHPExcel->getActiveSheet()->getProtection()->setSheet(true);

  8. Java练习 SDUT-1253_进制转换

    进制转换 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 输入一个十进制数N,将它转换成R进制数输出. Input 输入 ...

  9. Python基础:13装饰器

    装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的应用有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同 ...

  10. gcc需找头文件路径

    `gcc -print-prog-name=cc1plus` -v This command asks gcc which C++ preprocessor it is using, and then ...