bzoj2626 jzpfar 题解 题解: 代码:

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

题解:

kd-tree+priority_queue,套路题。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#define REP(i, a, b) for(LL i = a; i <= b; i ++)
#define REPG(i, x) for(LL i = head[x]; i; i = g[i].nxt)
#define oo 1e18 + 7
#define clr(x, y) memset(x, y, sizeof(x));
using namespace std;
typedef long long LL;
typedef double LF;
LL (LL a, LL b){return a > b ? a : b;}
LL Min(LL a, LL b){return a < b ? a : b;}
LL abs(LL x){return x > 0 ? x : -x;}
const LL MAXN = 1e5 + 15;
LL D, n, m, rt;
struct Node{
LL dist, id;
bool operator < (const Node &a) const{if(a.dist == dist) return id < a.id; return dist > a.dist;}
};
struct P{
LL d[2], mx[2], mn[2], l, r; LL id;
LL& operator[](LL x){return d[x];}
P(LL x = 0, LL y = 0){l = r = 0; d[0] = x, d[1] = y;}
}p[MAXN];
bool operator < (P a, P b){return a[D] < b[D];}
struct kdtree{
P T, t[MAXN]; priority_queue <Node> q;
void update(LL k){
P lson = t[t[k].l], rson = t[t[k].r];
for(LL i = 0; i < 2; i ++){
if(t[k].l) t[k].mn[i] = min(t[k].mn[i], lson.mn[i]), t[k].mx[i] = max(t[k].mx[i], lson.mx[i]);
if(t[k].r) t[k].mn[i] = min(t[k].mn[i], rson.mn[i]), t[k].mx[i] = max(t[k].mx[i], rson.mx[i]);
}
}
LL build(LL l, LL r, LL now){
D = now; LL mid = l + r >> 1;
nth_element(p + l, p + mid, p + r + 1);
t[mid] = p[mid];
for(LL i = 0; i < 2; i ++) t[mid].mn[i] = t[mid].mx[i] = t[mid][i];
if(l < mid) t[mid].l = build(l, mid - 1, now ^ 1);
if(r > mid) t[mid].r = build(mid + 1, r, now ^ 1);
update(mid);
return mid;
}
LL sqr(LL x){return x * x;}
LL getdist(LL k, P p){
LL ret = 0;
for(LL i = 0; i < 2; i ++) ret += sqr(t[k][i] - p[i]);
return ret;
}
LL get(LL k, P p){
LL ret = 0;
for(LL i = 0; i < 2; i ++) ret += Max(sqr(t[k].mn[i] - p[i]), sqr(t[k].mx[i] - p[i]));
return ret;
}
void qry(LL k){
LL d, dl = -2, dr = -2; d = getdist(k, T);
if(d > q.top().dist || (d == q.top().dist && t[k].id < q.top().id)) q.pop(), q.push((Node){d, t[k].id});
if(t[k].l) dl = get(t[k].l, T); if(t[k].r) dr = get(t[k].r, T);
if(dl > dr){
if(dl >= q.top().dist) qry(t[k].l);
if(dr >= q.top().dist) qry(t[k].r);
}
else{
if(dr >= q.top().dist) qry(t[k].r);
if(dl >= q.top().dist) qry(t[k].l);
}
}
void query(P p, LL h){
T = p; for(LL i = 1; i <= h; i ++) q.push((Node){-1, 0});
qry(rt);
printf("%lldn", q.top().id);
while(!q.empty()) q.pop();
}
}kd;
inline LL read(){
LL r = 0, z = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') z = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){r = r * 10 + ch - '0'; ch = getchar();}
return r * z;
}
void work(){
n = read();
for(LL i = 1; i <= n; i ++) p[i][0] = read(), p[i][1] = read(), p[i].id = i;
rt = kd.build(1, n, 0); m = read();
for(LL i = 1; i <= m; i ++){
LL x = read(), y = read(), h = read();
kd.query(P(x, y), h);
}
}
int main(){
work();
return 0;
}