[bzoj4520][kd-tree]K远点对
2017-11-24 13:44
295 查看
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
题解
自己写的模板打得不熟真的是硬伤
维护一个小根堆,堆的范围为2*k。表示前k长的距离。为啥要维护2*k个值?因为每条边都会被搜到两次啊
枚举每个点跑kdtree就好
估价函数出来的值比堆顶要大那就再进入kdtree跑,或者堆尚且不满2*k个
这样就轻松切掉了
其实我觉得暴力+优化都可以过这道题。。因为30s 不卡白不卡
已知平面内 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
题解
自己写的模板打得不熟真的是硬伤
维护一个小根堆,堆的范围为2*k。表示前k长的距离。为啥要维护2*k个值?因为每条边都会被搜到两次啊
枚举每个点跑kdtree就好
估价函数出来的值比堆顶要大那就再进入kdtree跑,或者堆尚且不满2*k个
这样就轻松切掉了
其实我觉得暴力+优化都可以过这道题。。因为30s 不卡白不卡
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> using namespace std; typedef long long LL; struct node { LL lc,rc,d[2],mx[2],mn[2]; }tr[810000]; priority_queue<LL,vector<LL>,greater<LL> > q; void update(int x) { int lc=tr[x].lc,rc=tr[x].rc; if(lc) { tr[x].mx[0]=max(tr[x].mx[0],tr[lc].mx[0]); tr[x].mn[0]=min(tr[x].mn[0],tr[lc].mn[0]); tr[x].mx[1]=max(tr[x].mx[1],tr[lc].mx[1]); tr[x].mn[1]=min(tr[x].mn[1],tr[lc].mn[1]); } if(rc) { tr[x].mx[0]=max(tr[x].mx[0],tr[rc].mx[0]); tr[x].mn[0]=min(tr[x].mn[0],tr[rc].mn[0]); tr[x].mx[1]=max(tr[x].mx[1],tr[rc].mx[1]); tr[x].mn[1]=min(tr[x].mn[1],tr[rc].mn[1]); } } int cmpd,root,n,k; bool cmp(node n1,node n2) { return n1.d[cmpd]<n2.d[cmpd] || n1.d[cmpd]==n2.d[cmpd] && n1.d[cmpd^1]<n2.d[cmpd^1]; } int bt(int l,int r,int d) { int mid=(l+r)/2,now; now=mid;cmpd=d; nth_element(tr+l,tr+mid,tr+r+1,cmp); tr[now].mx[0]=tr[now].mn[0]=tr[now].d[0]; tr[now].mx[1]=tr[now].mn[1]=tr[now].d[1]; if(l<mid)tr[now].lc=bt(l,mid-1,d^1); if(mid<r)tr[now].rc=bt(mid+1,r,d^1); update(now); return now; } LL getmax(int now,LL x,LL y) { return (max((tr[now].mx[0]-x)*(tr[now].mx[0]-x),(tr[now].mn[0]-x)*(tr[now].mn[0]-x))+max((tr[now].mx[1]-y)*(tr[now].mx[1]-y),(tr[now].mn[1]-y)*(tr[now].mn[1]-y))); } LL tmp[1110000];int len; LL maxx,nowx,nowy; void solmax(int now) { LL d0=(tr[now].d[0]-nowx)*(tr[now].d[0]-nowx)+(tr[now].d[1]-nowy)*(tr[now].d[1]-nowy); if(q.size()<2*k)q.push(d0); else if(d0>q.top() && q.size()==2*k)q.pop(),q.push(d0); LL dl=0,dr=0; if(tr[now].lc!=0)dl=getmax(tr[now].lc,nowx,nowy); if(tr[now].rc!=0)dr=getmax(tr[now].rc,nowx,nowy); if(dl<dr) { if(dr>q.top() || q.size()<2*k)solmax(tr[now].rc); if(dl>q.top() || q.size()<2*k)solmax(tr[now].lc); } else { if(dl>q.top() || q.size()<2*k)solmax(tr[now].lc); if(dr>q.top() || q.size()<2*k)solmax(tr[now].rc); } } int main() { scanf("%d%d",&n,&k); for(int i=1;i<=n;i++)scanf("%lld%lld",&tr[i].d[0],&tr[i].d[1]); root=bt(1,n,0); for(int i=1;i<=n;i++) { nowx=tr[i].d[0],nowy=tr[i].d[1]; solmax(root); } printf("%lld\n",q.top()); return 0; }
相关文章推荐
- bzoj4520 [Cqoi2016]K远点对(KDtree+stl)
- [ KD-tree ] [ CQOI2016 ] BZOJ4520
- bzoj 4520: [Cqoi2016]K远点对(KD-tree)
- [BZOJ4520][CQOI2016] K远点对 - KD-tree
- [KD-TREE 堆] BZOJ 4520 [Cqoi2016]K远点对
- [BZOJ4520][Cqoi2016]K远点对(KD-tree)
- 【kd-tree】BZOJ4520 CQOI2016K远点对
- 【BZOJ 4520】[Cqoi2016]K远点对 kd-tree
- BZOJ 4154(Generating Synergy-kd-tree代替树套树)
- bzoj 4066: 简单题 kd-tree
- BZOJ 1941: [Sdoi2010]Hide and Seek kdtree
- BZOJ 2648 kd-tree模板
- KD_Tree 【bzoj2648 && bzoj2716】SJY摆棋子 && [voilet 3] 天使玩偶
- BZOJ 2648 SJY摆棋子 ——KD-Tree
- BZOJ1176: [Balkan2007]Mokia kdtree
- bzoj 4520: [Cqoi2016]K远点对 k-d tree
- 【BZOJ2648】SYJ摆棋子 KD-Tree
- 【bzoj4520】[Cqoi2016]K远点对 KD-tree+堆
- BZOJ 4520 [Cqoi2016]K远点对(KD-tree+堆)
- 【BZOJ3053】The Closest M Points KDtree 好模板一只【数组版!!!】