[BZOJ4520][Cqoi2016]K远点对 kd-tree 优先队列

二次信任 提交于 2020-02-06 01:44:24

4520: [Cqoi2016]K远点对

Time Limit: 30 Sec  Memory Limit: 512 MB
Submit: 1285  Solved: 708
[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

HINT

 

Source

 

kd-tree可以查询每个点到其他点的距离。

我们求出每两个点间的距离,随后求出第2*k大值即可。

用优先队列维护前2*k大值,在kd-tree上查询并修改即可。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<queue>
 8 #define ll long long
 9 #define maxn 100005
10 using namespace std;
11 inline int read() {
12     int x=0,f=1;char ch=getchar();
13     for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
14     for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
15     return x*f;
16 }
17 int nowd=0,rt,n,k;
18 struct node {ll d[2],mx[2],mn[2],l,r;}t[maxn];
19 bool cmp(node t1,node t2) {return t1.d[nowd]<t2.d[nowd];}
20 priority_queue<ll,vector<ll>,greater<ll> >q;ll cnt=0;
21 void pushup(int x) {
22     int l=t[x].l,r=t[x].r;
23     if(l) {
24         t[x].mx[0]=max(t[x].mx[0],t[l].mx[0]);
25         t[x].mx[1]=max(t[x].mx[1],t[l].mx[1]);
26         t[x].mn[0]=min(t[x].mn[0],t[l].mn[0]);
27         t[x].mn[1]=min(t[x].mn[1],t[l].mn[1]);
28     }
29     if(r) {
30         t[x].mx[0]=max(t[x].mx[0],t[r].mx[0]);
31         t[x].mx[1]=max(t[x].mx[1],t[r].mx[1]);
32         t[x].mn[0]=min(t[x].mn[0],t[r].mn[0]);
33         t[x].mn[1]=min(t[x].mn[1],t[r].mn[1]);
34     }
35 }
36 int build(int l,int r,bool D) {
37     int mid=l+r>>1;nowd=D;
38     nth_element(t+l,t+mid,t+r+1,cmp);
39     if(l<mid) t[mid].l=build(l,mid-1,!D);
40     if(r>mid) t[mid].r=build(mid+1,r,!D);
41     t[mid].mx[0]=t[mid].mn[0]=t[mid].d[0];
42     t[mid].mx[1]=t[mid].mn[1]=t[mid].d[1];
43     pushup(mid);
44     return mid;
45 }
46 ll dis(int x,int y) {return (t[x].d[0]-t[y].d[0])*(t[x].d[0]-t[y].d[0])+(t[x].d[1]-t[y].d[1])*(t[x].d[1]-t[y].d[1]);}
47 ll gdis(int x,int y) {
48     return max((t[x].mn[0]-t[y].d[0])*(t[x].mn[0]-t[y].d[0]),(t[x].mx[0]-t[y].d[0])*(t[x].mx[0]-t[y].d[0]))+max((t[x].mn[1]-t[y].d[1])*(t[x].mn[1]-t[y].d[1]),(t[x].mx[1]-t[y].d[1])*(t[x].mx[1]-t[y].d[1]));
49 }
50 void query(int x,int y) {
51     if(!x) return;
52     ll now=dis(x,y);
53     if(now>q.top()) {q.pop();q.push(now);}
54     ll dl=0,dr=0;
55     if(t[x].l) dl=gdis(t[x].l,y);if(t[x].r) dr=gdis(t[x].r,y);
56     if(dl>dr) {
57         if(dl>q.top()) query(t[x].l,y);
58         if(dr>q.top()) query(t[x].r,y);
59     }
60     else {
61         if(dr>q.top()) query(t[x].r,y);
62         if(dl>q.top()) query(t[x].l,y);
63     }
64 }
65 int main() {
66     n=read();k=read();
67     for(int i=1;i<=n;i++) t[i].d[0]=read(),t[i].d[1]=read();
68     rt=build(1,n,0);
69     for(int i=1;i<=k*2;i++) q.push(0);
70     for(int i=1;i<=n;i++) query(rt,i);
71     printf("%lld\n",q.top());
72 }
View Code

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!