[BZOJ][KD-tree]2626: JZPFAR

来源:互联网 发布:python cuda编程 编辑:程序博客网 时间:2024/04/30 22:31

题目

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+优先队列就可以A,因为只有2维,KD-tree还是比较好打的吧。然后就是正常的建树,查询。

代码

#include <cstdio>#include <queue>#include <algorithm>#include <cmath>#include <cstdlib>using namespace std;#define N 100000inline char tc(void){    static char fl[100000],*A=fl,*B=fl;    return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;}inline int read(void){    int a=0,f=1;static char c;    while((c=tc())<'0'||c>'9')c=='-'?f=-1:0;    while(c>='0'&&c<='9')a=a*10+c-'0',c=tc();    return a*f;}inline int max(int a,int b){    return a>b?a:b;}inline int min(int a,int b){    return a<b?a:b;}int n,m,root,D,x,y,k,ans;double dis1,dis2;struct Y{    int d[2],mx[2],mix[2],l,r,h;    inline bool operator <(const Y&a) const{        return d[D]<a.d[D];     }}a[N+2];struct M{    int h;    double dis;    inline bool operator <(const M&a) const{        return dis>a.dis||dis==a.dis&&h<a.h;    }}o;priority_queue<M> s;void update(int k,int s){    a[k].mx[0]=max(a[k].mx[0],a[s].mx[0]),      a[k].mx[1]=max(a[k].mx[1],a[s].mx[1]),    a[k].mix[0]=min(a[k].mix[0],a[s].mix[0]),    a[k].mix[1]=min(a[k].mix[1],a[s].mix[1]);    return ;}int build(int l,int r,int dd){    int mid=l+r>>1;D=dd;    nth_element(a+l+1,a+mid+1,a+r+1);    a[mid].mix[0]=a[mid].mx[0]=a[mid].d[0],    a[mid].mix[1]=a[mid].mx[1]=a[mid].d[1];    if(l!=mid) a[mid].l=build(l,mid-1,dd^1);    else a[mid].l=0;    if(r!=mid) a[mid].r=build(mid+1,r,dd^1);    else a[mid].r=0;    if(a[mid].l) update(mid,a[mid].l);    if(a[mid].r) update(mid,a[mid].r);    return mid;}double distance(int w){    double dis1=0;    dis1+=max(double(x-a[w].mix[0])*(x-a[w].mix[0]),double(x-a[w].mx[0])*(x-a[w].mx[0]));    dis1+=max(double(y-a[w].mix[1])*(y-a[w].mix[1]),double(y-a[w].mx[1])*(y-a[w].mx[1]));    return dis1;}void query(int now,int dd){    double dis1,dis2;    o.h=a[now].h,o.dis=1ll*(a[now].d[0]-x)*(a[now].d[0]-x)+1ll*(a[now].d[1]-y)*(a[now].d[1]-y),D=dd;    if(s.size()<k) s.push(o);    else if(o<s.top()) s.pop(),s.push(o);    if(a[now].l)dis1=distance(a[now].l);    else dis1=-1;    if(a[now].r)dis2=distance(a[now].r);    else dis2=-1;    if(dis1>dis2){        if(dis1>=0&&(s.size()<k||dis1>=s.top().dis)) query(a[now].l,dd^1);        if(dis2>=0&&(s.size()<k||dis2>=s.top().dis)) query(a[now].r,dd^1);    }    else{        if(dis2>=0&&(s.size()<k||dis2>=s.top().dis)) query(a[now].r,dd^1);        if(dis1>=0&&(s.size()<k||dis1>=s.top().dis)) query(a[now].l,dd^1);    }    return ;}int main(void){    freopen("2626.in","r",stdin);    freopen("2626.out","w",stdout);    register int i;    n=read();    for (i=1;i<=n;++i)        a[i].d[0]=read(),a[i].d[1]=read(),a[i].h=i;    root=build(1,n,0),m=read();    for (i=1;i<=m;++i){        x=read(),y=read(),k=read(),query(root,0);        ans=s.top().h;        while(!s.empty())            s.pop();        printf("%d\n",ans);    }    return 0;}