Luo Gu P2093 [National Team] JZPFAR [KD tree + heap seek far point k]

Subject description:

There are n points on a plane. There are m times asked each time a given point (px, py), and an integer k, the n outputs reference point of the k-th from the large dots (px, py) distance. If there are two (or more) from the same points (px, py), so that a smaller reference point distance is large.
100% of the data, n <= 10 ^ 5, m <= 10 ^ 4, 1 <= k <= 20, all points (including the query point) satisfies an absolute value of the coordinates of <= 10 ^ 9, n points any two points in a different coordinate, m is an interrogation coordinate points randomly distributed within a certain range.

Topic analysis:

KD + small tree root maintain large heap before k.
If the heap size is not reached k, directly into the current point.
If the size of the stack and the current point of greater than k reaches the top of the stack pop top of the heap, stack current insertion point.

If k reaches the stack size and the maximum estimated subtree is not less than the top of the stack downward.

Note KD tree to go big valuation function the other way when his son to go.

Code:

#include<bits/stdc++.h>
#define maxn 100005
#define LL long long
using namespace std;
char cb[1<<18],*cs,*ct;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<18,stdin),cs==ct)?0:*cs++)
inline void read(int &a){
	char c;bool f=0;while(!isdigit(c=getc())) c=='-'&&(f=1);
	for(a=c-'0';isdigit(c=getc());a=a*10+c-'0'); f&&(a=-a);	
}
const LL inf = 9223372036854775806ll;
int n,m,k,id[maxn],rt,X,Y;
struct node{
	int d[2],mn[2],mx[2],ch[2];
	void upd(node *t){
		mn[0]=mx[0]=d[0],mn[1]=mx[1]=d[1];
		for(int i=0;i<2;i++) if(ch[i]) for(int j=0;j<2;j++) mn[j]=min(mn[j],t[ch[i]].mn[j]),mx[j]=max(mx[j],t[ch[i]].mx[j]);	
	}
}t[maxn];
struct Pt{
	LL x;int y;
	bool operator < (const Pt &p)const{return x==p.x?y<p.y:x>p.x;}
};
priority_queue<Pt>S;
template<int D>bool cmp(int i,int j){return t[i].d[D]<t[j].d[D];}
bool (*fun[2])(int i,int j)={cmp<0>,cmp<1>};
void build(int &i,int l,int r,int D){
	if(l>r) {i=0;return;}
	int o=(l+r)>>1;nth_element(id+l,id+o,id+r+1,fun[D]),i=id[o];
	build(t[i].ch[0],l,o-1,D^1),build(t[i].ch[1],o+1,r,D^1);
	t[i].upd(t);
}
#define sqr(x) (1ll*(x)*(x))
inline LL G(int i){
	if(!i) return inf;
	return max(sqr(X-t[i].mn[0]),sqr(X-t[i].mx[0]))+max(sqr(Y-t[i].mn[1]),sqr(Y-t[i].mx[1]));
}
inline void ins(int i){
	Pt now=(Pt){sqr(X-t[i].d[0])+sqr(Y-t[i].d[1]),i};
	if(S.size()<k) S.push(now);
	else if(now<S.top()) S.pop(),S.push(now);
}
void query(int i){
	//if(!i) return;
	ins(i);
	LL tmp[2]={G(t[i].ch[0]),G(t[i].ch[1])};int p=tmp[1]>tmp[0];
	if(t[i].ch[p]&&(S.size()<k||tmp[p]>=S.top().x)) query(t[i].ch[p]);
	p^=1;
	if(t[i].ch[p]&&(S.size()<k||tmp[p]>=S.top().x)) query(t[i].ch[p]);
}
int main()
{
	read(n);
	for(int i=1;i<=n;i++) id[i]=i,read(t[i].d[0]),read(t[i].d[1]);
	build(rt,1,n,0);
	read(m);
	while(m--){
		read(X),read(Y),read(k);
		while(!S.empty()) S.pop();
		query(rt);
		printf("%d\n",S.top().y);
	}
}

Published 344 original articles · won 127 Like · views 50000 +

Guess you like

Origin blog.csdn.net/C20181220_xiang_m_y/article/details/103994443