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 ",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; }