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. 2019-3-27-win10-uwp-动画移动滑动条的滑块

    title author date CreateTime categories win10 uwp 动画移动滑动条的滑块 lindexi 2019-03-27 10:51:32 +0800 2019- ...

  2. C#总结 标签: c# 2014-12-07 19:07 1148人阅读 评论(47) 收藏

    之前考二级的时候,C++没有好好的学,如今到了学C#的时候,又重新明白了一遍出来混,迟早要还得道理,我觉得,其实C#比C++简单,应该是因为之前没有好好学得原因,其实现在学C#,也是和一年前一样,照着 ...

  3. OpenJudge_1477:Box of Bricks

    描述 Little Bob likes playing with his box of bricks. He puts the bricks one upon another and builds s ...

  4. AT3728 Squirrel Migration

    AT3728 Squirrel Migration 就是给每个点分配两个匹配点(自环除外) 考虑最大值 考虑极限情况:每个边的贡献是min(sz[u],sz[v])*2 证明存在方案: 发现,如果哪边 ...

  5. HDU-1260_Tickets

    Tickets Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Problem Des ...

  6. DRDS 数据恢复重磅发布,全方位保障您的数据安全

    背景介绍 数据库存储着企业的核心数据,在企业中占据非常重要的位置,一旦出现SQL注入,数据误删的情况,影响的不仅仅是业务,还会泄露用户的个人信息.因此,数据库的数据安全问题十分重要. 当数据库迁移到云 ...

  7. genymotion 和genymotion eclipse 插件安装 !

    昨天天有好心网友在群里共享了一个好用的 android 模拟器 genymotion 昨天就试用了下 真心流畅 各位不妨一试 http://www.genymotion.com/ doc https: ...

  8. oracle函数 SUBSTR(c1,n1[,n2])

    [功能]取子字符串 [说明]多字节符(汉字.全角符等),按1个字符计算 [参数]在字符表达式c1里,从n1开始取n2个字符;若不指定n2,则从第y个字符直到结束的字串. [返回]字符型 [示例] SQ ...

  9. @bzoj - 3750@ [POI2015] Pieczęć

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 一张 n*m 的方格纸,有些格子需要印成黑色,剩下的格子需要保留 ...

  10. 「BZOJ1005」[HNOI2008] 明明的烦恼

    「BZOJ1005」[HNOI2008] 明明的烦恼 先放几个prufer序列的结论: Prufer序列是一种对有标号无根树的编码,长度为节点数-2. 具体存在无根树转化为prufer序列和prufe ...