您的位置:首页 > 其它

【BZOJ 4520】[Cqoi2016]K远点对 kd-tree

2017-02-17 15:40 309 查看
迷之复杂度。。。。。。

总感觉kd-tree的复杂度很迷,毕竟搜索嘛,可是剪枝居然这么强也是够了,所以我感觉以后遇见kd-tree的题目真的就别想什么T了,暴力出奇迹

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<algorithm>
#define inf 0x3fffffff
#define maxn 200021
#define ls nod[u].l
#define rs nod[u].r
#define LL long long
using namespace std;
int n,K,pos,rt;LL dx,dy;
priority_queue<LL,vector<LL>,greater<LL> >q;
struct node{
int l,r;
LL Max[2],Min[2],d[2];
bool operator<(const node& y)const{
return d[pos]==y.d[pos] ? d[pos^1]<y.d[pos^1] : d[pos]<y.d[pos];
}
}nod[maxn];
void push_up(int u){
for(int i=0;i<2;i++){
nod[u].Max[i]=max(nod[u].d[i],max(nod[ls].Max[i],nod[rs].Max[i]));
nod[u].Min[i]=min(nod[u].d[i],min(nod[ls].Min[i],nod[rs].Min[i]));
}
}
int build(int l,int r,int k){
if(l>r)return 0;
int mid=l+r>>1;
pos=k;nth_element(nod+l+1,nod+1+mid,nod+1+r);
if(l<mid)nod[mid].l=build(l,mid-1,k^1);
if(r>mid)nod[mid].r=build(mid+1,r,k^1);
push_up(mid);
return mid;
}
inline LL sqr(LL x){return x*x;}
inline LL Q(int a){return sqr(nod[a].d[0]-dx)+sqr(nod[a].d[1]-dy);}
inline LL dis2(LL a,LL b){return sqr(a-dx)+sqr(b-dy);}
LL guess(int a){
LL ans=0;
ans=max(ans,dis2(nod[a].Max[0],nod[a].Max[1]));
ans=max(ans,dis2(nod[a].Max[0],nod[a].Min[1]));
ans=max(ans,dis2(nod[a].Min[0],nod[a].Max[1]));
ans=max(ans,dis2(nod[a].Min[0],nod[a].Min[1]));
return ans;
}
void query(int u){
if(!u)return;
LL ans=Q(u),ansl=guess(nod[u].l),ansr=guess(nod[u].r);
if(ans>q.top())q.pop(),q.push(ans);
if(ansl>ansr){
if(ansl>q.top())query(ls);
if(ansr>q.top())query(rs);
}else{
if(ansr>q.top())query(rs);
if(ansl>q.top())query(ls);
}
}
int main(){
nod[0].Min[0]=nod[0].Min[1]=inf;
nod[0].Max[0]=nod[0].Max[1]=-inf;
scanf("%d%d",&n,&K);for(int i=1;i<=2*K;i++)q.push(0);
for(int i=1;i<=n;i++)scanf("%lld%lld",&nod[i].d[0],&nod[i].d[1]);
rt=build(1,n,0);
for(int i=1;i<=n;i++){
dx=nod[i].d[0],dy=nod[i].d[1];
query(rt);
}printf("%lld",q.top());
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: