1. 程式人生 > >【BZOJ2626】JZPFAR kd-tree+堆

【BZOJ2626】JZPFAR kd-tree+堆

long long print prior ros strong led queue 整數 cond

【BZOJ2626】JZPFAR

Description

  平面上有n個點。現在有m次詢問,每次給定一個點(px, py)和一個整數k,輸出n個點中離(px, py)的距離第k大的點的標號。如果有兩個(或多個)點距離(px, py)相同,那麽認為標號較小的點距離較大。

Input

  第一行,一個整數n,表示點的個數。
  下面n行,每行兩個整數x_i, y_i,表示n個點的坐標。點的標號按照輸入順序,分別為1..n。
  下面一行,一個整數m,表示詢問個數。
  下面m行,每行三個整數px_i, py_i, k_i,表示一個詢問。

Output

  m行,每行一個整數,表示相應的詢問的答案。

Sample Input

3
0 0
0 1
0 2
3
1 1 2
0 0 3
0 1 1

Sample Output

3
1
1

數據規模和約定
  50%的數據中,n個點的坐標在某範圍內隨機分布。
  100%的數據中,n<=10^5, m<=10^4, 1<=k<=20,所有點(包括詢問的點)的坐標滿足絕對值<=10^9,n個點中任意兩點坐標不同,m個詢問的點的坐標在某範圍內隨機分布。

題解:kd-tree+一個最小堆。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <utility>
#define x2(_) ((_)*(_))
#define rep for(int i=0;i<=1;i++)
#define MP(A,B)	make_pair(A,B)
using namespace std;
typedef long long ll;
typedef pair<ll,int> pli;
const int maxn=100010;
struct kd
{
	ll v[2],sm[2],sn[2];
	int ls,rs,org,om;
	kd () {}
	kd (ll a,ll b,int c)	{v[0]=sm[0]=sn[0]=a,v[1]=sm[1]=sn[1]=b,ls=rs=0,org=om=c;}
	ll& operator [] (int a) {return v[a];}
}t[maxn];
int n,m,D,A,B,root;
priority_queue<pli> pq;
int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<‘0‘||gc>‘9‘)	{if(gc==‘-‘)f=-f;	gc=getchar();}
	while(gc>=‘0‘&&gc<=‘9‘)	ret=ret*10+gc-‘0‘,gc=getchar();
	return ret*f;
}
bool cmp(kd a,kd b)
{
	return (a[D]==b[D])?(a[D^1]<b[D^1]):(a[D]<b[D]);
}
void pushup(int x,int y)
{
	rep	t[x].sm[i]=max(t[x].sm[i],t[y].sm[i]),t[x].sn[i]=min(t[x].sn[i],t[y].sn[i]);
	t[x].om=min(t[x].om,t[y].om);
}
int build(int l,int r,int d)
{
	if(l>r)	return 0;
	int mid=l+r>>1;
	D=d,nth_element(t+l,t+mid,t+r+1,cmp);
	t[mid].ls=build(l,mid-1,d^1),t[mid].rs=build(mid+1,r,d^1);
	if(t[mid].ls)	pushup(mid,t[mid].ls);
	if(t[mid].rs)	pushup(mid,t[mid].rs);
	return mid;
}
pli getdis(int x)
{
	return MP(-max(x2(t[x].sm[0]-A),x2(t[x].sn[0]-A))-max(x2(t[x].sm[1]-B),x2(t[x].sn[1]-B)),t[x].om);
}
void query(int x)
{
	if(!x||getdis(x)>pq.top())	return ;
	pli tmp=MP(-x2(t[x][0]-A)-x2(t[x][1]-B),t[x].org);
	if(tmp<pq.top())
		pq.push(tmp),pq.pop();
	if(getdis(t[x].ls)<getdis(t[x].rs))	query(t[x].ls),query(t[x].rs);
	else	query(t[x].rs),query(t[x].ls);
}
int main()
{
	n=rd();
	int i,j,a,b,c;
	for(i=1;i<=n;i++)	a=rd(),b=rd(),t[i]=kd(a,b,i);
	root=build(1,n,0);
	m=rd();
	for(i=1;i<=m;i++)
	{
		A=rd(),B=rd(),c=rd();
		while(!pq.empty())	pq.pop();
		for(j=1;j<=c;j++)	pq.push(MP(1ll<<60,-1<<30));
		query(root);
		printf("%d\n",pq.top().second);
	}
	return 0;
}
//3 0 0 0 1 0 2 3 1 1 2 0 0 3 0 1 1 

【BZOJ2626】JZPFAR kd-tree+堆