BZOJ2626: JZPFAR

BZOJ2626: JZPFAR

BZOJ氪金无极限。。。

洛谷大好!

洛谷P2093 [国家集训队]JZPFAR

题目描述

平面上有n个点。现在有m次询问,每次给定一个点(px, py)和一个整数k,输出n个点中离(px, py)的距离第k大的点的标号。

如果有两个(或多个)点距离(px, py)相同,那么认为标号较小的点距离较大。

输入输出格式

输入格式:

 

第一行,一个整数n,表示点的个数。

下面n行,每行两个整数x_i, y_i,表示n个点的坐标。点的标号按照输入顺序,分别为1..n。

下面一行,一个整数m,表示询问个数。

下面m行,每行三个整数px_i, py_i, k_i,表示一个询问。

 

输出格式:

 

m行,每行一个整数,表示相应的询问的答案。

 

输入输出样例

输入样例: 
3
0 0
0 1
0 2
3
1 1 2
0 0 3
0 1 1
输出样例: 
3
1
1

说明

50%的数据中,n个点的坐标在某范围内随机分布。

100%的数据中,n<=10^5, m<=10^4, 1<=k<=20,所有点(包括询问的点)的坐标满足绝对值<=10^9,n个点中任意两点坐标不同,m个询问的点的坐标在某范围内随机分布。


题解Here!

其实是一道裸的$K-D \ Tree$。

但是本蒟蒻表示并不能理解。。。

于是对着板子敲了一遍。。。

连我自己都不知道我怎么$WA$的,又是怎么$AC$的。。。

附代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#define MAXN 101000
#define MAX (1LL<<60)
using namespace std;
int n,m,root;
bool sort_flag=false;
struct Point{
	int id;
	long long x,y;
	friend bool operator <(const Point &p,const Point &q){
		if(sort_flag)return p.y<q.y;
		return p.x<q.x;
	}
}point[MAXN],now;
struct Tree{
	Point point;
	long long minx,miny,maxx,maxy;
	int lson,rson,minid;
	Tree(){minid=2147483646;}
}a[MAXN];
struct Heap{
	int id;
	long long dis;
	friend bool operator <(const Heap &p,const Heap &q){
		if(p.dis==q.dis)return p.id<q.id;
		return p.dis>q.dis;
	}
};
priority_queue<Heap> heap;
inline int read(){
	int date=0,w=1;char c=0;
	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
	return date*w;
}
inline long long get_dis(const Point &p,const Point &q){
	return (p.x-q.x)*(p.x-q.x)+(p.y-q.y)*(p.y-q.y);
}
inline void pushup(int rt){
	int lson=a[rt].lson,rson=a[rt].rson;
	a[rt].minid=min(a[rt].point.id,min(a[lson].minid,a[rson].minid));
	a[rt].maxx=max(a[rt].maxx,max(a[lson].maxx,a[rson].maxx));
	a[rt].maxy=max(a[rt].maxy,max(a[lson].maxy,a[rson].maxy));
	a[rt].minx=min(a[rt].minx,min(a[lson].minx,a[rson].minx));
	a[rt].miny=min(a[rt].miny,min(a[lson].miny,a[rson].miny));
}
void buildtree(int l,int r,int &rt,int flag){
	int mid=l+r>>1;
	rt=mid;
	sort_flag=flag;
	nth_element(point+l,point+mid,point+r+1);
	a[rt].point=point[mid];
	a[rt].minx=a[rt].maxx=point[mid].x;
	a[rt].miny=a[rt].maxy=point[mid].y;
	if(l<mid)buildtree(l,mid-1,a[rt].lson,flag^1);
	if(mid<r)buildtree(mid+1,r,a[rt].rson,flag^1);
	pushup(rt);
}
inline long long max_dis(int rt){
	long long x,y;
	x=max(abs(now.x-a[rt].minx),abs(now.x-a[rt].maxx));
	y=max(abs(now.y-a[rt].miny),abs(now.y-a[rt].maxy));
	return (x*x+y*y);
}
void query(int rt){
	int id=a[rt].point.id;
	long long dis=get_dis(a[rt].point,now),ldis=-MAX,rdis=-MAX;
	if((Heap){id,dis}<heap.top()){
		heap.pop();
		heap.push((Heap){id,dis});
	}
	if(a[rt].lson)ldis=max_dis(a[rt].lson);
	if(a[rt].rson)rdis=max_dis(a[rt].rson);
	if(ldis>rdis){
		if((Heap){a[a[rt].lson].minid,ldis}<heap.top())query(a[rt].lson);
		if((Heap){a[a[rt].rson].minid,rdis}<heap.top())query(a[rt].rson);
	}
	else{
		if((Heap){a[a[rt].rson].minid,rdis}<heap.top())query(a[rt].rson);
		if((Heap){a[a[rt].lson].minid,ldis}<heap.top())query(a[rt].lson);
	}
}
void work(){
	int k;
	while(m--){
		while(!heap.empty())heap.pop();
		now.x=read();now.y=read();k=read();
		while(k--)heap.push((Heap){0,-MAX});
		query(root);
		printf("%d\n",heap.top().id);
	}
}
void init(){
	n=read();
	a[0].maxx=a[0].maxy=-MAX;
	a[0].minx=a[0].miny=MAX;
	for(int i=1;i<=n;i++){
		point[i].x=read();point[i].y=read();
		point[i].id=i;
	}
	m=read();
	buildtree(1,n,root,0);
}
int main(){
	init();
	work();
	return 0;
}

 

posted @ 2019-04-03 22:30  符拉迪沃斯托克  阅读(321)  评论(0编辑  收藏  举报
Live2D