【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;
}

發佈了61 篇原創文章 · 獲贊 1 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章