BZOJ 2626 JZPFAR(KD-tree)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2626

题意:平面上有n个点。现在有m次询问,每次给定一个点(px, py)和一个整数k,输出n个点中离(px, py)的距离第k大的点的标号。如果有两个(或多个)点距离(px, py)相同,那么认为标号较小的点距离较大。

思路:对n个点做KDtree。

 1 #include<algorithm>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<iostream>
 6 #define ll long long
 7 struct Point{
 8     ll d[2],max[2],min[2];
 9     int l,r,id;
10 }a[500005];
11 int root,n,K,cmpd,id[50],m;
12 ll X,Y,ans[50];
13 bool cmp(Point p1,Point p2){
14     if (p1.d[cmpd]!=p2.d[cmpd]) return p1.d[cmpd]<p2.d[cmpd];
15     else return p1.d[!cmpd]<p2.d[!cmpd];
16 }
17 void updata(int x){
18     if (a[x].l){
19         int j=a[x].l;
20         for (int i=0;i<2;i++)
21          a[x].max[i]=std::max(a[x].max[i],a[j].max[i]),
22          a[x].min[i]=std::min(a[x].min[i],a[j].min[i]);
23     }
24     if (a[x].r){
25         int j=a[x].r;
26         for (int i=0;i<2;i++)
27          a[x].max[i]=std::max(a[x].max[i],a[j].max[i]),
28          a[x].min[i]=std::min(a[x].min[i],a[j].min[i]);
29     }
30 }
31 ll sqr(ll x){
32     return x*x;
33 }
34 ll dist(int p,ll x,ll y){
35     ll dis=0,d1,d2;
36     d1=std::abs(x-a[p].max[0]);
37     d2=std::abs(x-a[p].min[0]);
38     if (d1>d2) dis+=d1*d1;
39     else dis+=d2*d2;
40     d1=std::abs(y-a[p].max[1]);
41     d2=std::abs(y-a[p].min[1]);
42     if (d1>d2) dis+=d1*d1;
43     else dis+=d2*d2;
44     return dis;
45 }
46 void query(int p){
47     if (!p) return;
48     ll dl,dr,d0;
49     int t=K;
50     d0=sqr(std::abs(a[p].d[0]-X))+sqr(std::abs(a[p].d[1]-Y));
51     while (t&&(d0>ans[t]||(d0==ans[t]&&a[p].id<id[t]))) t--;
52     if (t!=K){
53      t++;
54      for (int i=K;i>=t+1;i--){
55       ans[i]=ans[i-1];
56       id[i]=id[i-1];
57       }
58      ans[t]=d0;id[t]=a[p].id; 
59     }
60     if (a[p].l) dl=dist(a[p].l,X,Y);else dl=0;
61     if (a[p].r) dr=dist(a[p].r,X,Y);else dr=0;
62     if (dl>dr){
63         if (dl>=ans[K]) query(a[p].l);
64         if (dr>=ans[K]) query(a[p].r);
65     }else{
66         if (dr>=ans[K]) query(a[p].r);
67         if (dl>=ans[K]) query(a[p].l);
68     }
69 }
70 int build(int l,int r,int d){
71     int mid=(l+r)/2;
72     cmpd=d;
73     std::nth_element(a+l,a+mid,a+1+r,cmp);
74     a[mid].max[0]=a[mid].min[0]=a[mid].d[0];
75     a[mid].max[1]=a[mid].min[1]=a[mid].d[1];
76     if (l!=mid) a[mid].l=build(l,mid-1,!d);
77     if (r!=mid) a[mid].r=build(mid+1,r,!d);
78     updata(mid);
79     return mid;
80 }
81 int main(){
82     scanf("%d",&n);
83     for (int i=1;i<=n;i++){
84      scanf("%lld%lld",&a[i].d[0],&a[i].d[1]);
85      a[i].id=i;
86     }
87     root=build(1,n,0);
88     scanf("%d",&m);
89     while (m--){
90         scanf("%lld%lld%d",&X,&Y,&K);
91         for (int i=0;i<=20;i++) id[i]=99999999,ans[i]=0;
92         query(root);
93         printf("%d\n",id[K]); 
94     }
95 }

 

posted @ 2016-06-02 16:30  GFY  阅读(313)  评论(0编辑  收藏  举报