[BZOJ4520][Cqoi2016]K远点对 kd-tree 优先队列
4520: [Cqoi2016]K远点对
Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 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
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 }
O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~