【BZOJ4520】【Cqoi2016】K远点对 K-DTree

所以说CQ冷门模板默写大会真的不是吹的科科,话说一天到晚给BZOJ贡献双倍经验真的大丈夫吗

K-D Tree裸题,主要结构其实是一棵二叉搜索树,交替以横坐标和纵坐标作为第一关键字,把中位数当成根递归构建树,这样每一个节点代表原图的一个矩形区间,当且仅当这个矩形的四个顶点离查询点的距离的最大值大于小根堆的堆顶时才继续向下搜索。其实第一反应丫就是强剪枝对不对!

#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
#define maxn 100005
#define oo 999999999
void _readLL(long long &x){x=0; char ch=getchar(); bool flag=false;while(ch<'0'||ch>'9'){if(ch=='-')flag=true; ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}if(flag)x=-x; return ;}
int n,k,Q,chi[maxn][2],rt;
long long minv[maxn][2],maxv[maxn][2];
struct data{long long d[2];}A[maxn],v;
long long getdis(data x,data y){return (x.d[0]-y.d[0])*(x.d[0]-y.d[0]) + (x.d[1]-y.d[1])*(x.d[1]-y.d[1]);}
bool operator < (data x,data y){return x.d[Q]==y.d[Q]?x.d[Q^1]<y.d[Q^1] : x.d[Q]<y.d[Q]; }
void Init(){scanf("%d%d",&n,&k);for(int i=1;i<=n;i++){_readLL(A[i].d[0]);_readLL(A[i].d[1]);}}
void push_up(int now)
{
	for(int i=0;i<=1;i++)
	{
		minv[now][i]=min(A[now].d[i],min(minv[chi[now][0]][i],minv[chi[now][1]][i]));
		maxv[now][i]=max(A[now].d[i],max(maxv[chi[now][0]][i],maxv[chi[now][1]][i]));
	}
	return ;
}
void build(int &now,int L,int R,int k)
{
	if(L>R){now=0; return ;}
	now=(L+R)>>1;
	Q=k;
	nth_element(A+L,A+now,A+R+1);
	if(L<now)build(chi[now][0],L,now-1,k^1);else chi[now][0]=0; if(R>now)build(chi[now][1],now+1,R,k^1);else chi[now][1]=0;
	push_up(now);
	return ;
}
struct cmp1
{
	bool operator () (long long x,long long y)
	{
		return x>y;
	}
};
priority_queue<long long ,vector<long long> ,cmp1>pq;
long long get(int x){if(!x)return 0; return max((minv[x][0]-v.d[0])*(minv[x][0]-v.d[0]),(maxv[x][0]-v.d[0])*(maxv[x][0]-v.d[0]))+max((minv[x][1]-v.d[1])*(minv[x][1]-v.d[1]),(maxv[x][1]-v.d[1])*(maxv[x][1]-v.d[1]));}
void query(int now)
{
	if(!now)return ;
	long long d=getdis(A[now],v),dl=get(chi[now][0]),dr=get(chi[now][1]);
	if(d>pq.top()){pq.pop(); pq.push(d);};
	if(dl>dr)
	{
		if(dl>pq.top() && chi[now][0])query(chi[now][0]); if(dr>pq.top() && chi[now][1])query(chi[now][1]);
	}
	else
	{
		if(dr>pq.top() && chi[now][1])query(chi[now][1]); if(dl>pq.top() && chi[now][0])query(chi[now][0]); 
	}
	return ;
}
void work()
{
	minv[0][0]=minv[0][1]=oo;maxv[0][0]=maxv[0][1]=-oo; //懒得处理边界了 
	build(rt,1,n,0);
	for(int i=2*k;i;i--)pq.push(0);
	for(int i=1;i<=n;i++) 
	{
		v=A[i]; query(rt);
	}
	cout<<pq.top()<<endl;
	return ;
}
int main()
{
	freopen("in.txt","r",stdin);
	Init();
	work();
	return 0;
}

你可能感兴趣的:(【BZOJ4520】【Cqoi2016】K远点对 K-DTree)