BZOJ氪金无极限。。。
洛谷大好!
题目描述
平面上有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行,每行一个整数,表示相应的询问的答案。
输入输出样例
说明
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;
}