P2093 [国家集训队]JZPFAR
P2093 [国家集训队]JZPFAR
https://www.luogu.org/problemnew/show/P2093
分析:
kdtree模板
维护一个小根堆,开始时插入k个-inf,每次取出最小的与当前更新,如果当前的更大一些,那么更新堆中的元素。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 5 inline int read() { 6 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 7 for (;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; 8 } 9 10 const int N = 200010; 11 const int DIM = 2; 12 const LL INF = 1e9; 13 14 struct Point{ 15 LL x[2];int id; 16 Point() {x[0] = 0;x[1] = 0;} 17 Point(LL a,LL b) {x[0] = a,x[1] = b;} 18 LL& operator[](int c){return x[c];} 19 }P[N],Q; 20 struct KDtree{ 21 int ch[2],mn[2],mx[2]; 22 Point p; 23 }T[N<<1]; 24 struct State{ 25 LL dis;int id; 26 State() {} 27 State(LL a,LL b) {dis = a,id = b;} 28 bool operator < (const State &A) const { 29 if (dis == A.dis) return id < A.id; 30 return dis > A.dis; 31 } 32 }; 33 priority_queue <State> q; 34 int Cur,CntNode,Root; 35 36 #define lc T[rt].ch[0] 37 #define rc T[rt].ch[1] 38 39 bool cmp(Point a,Point b) { 40 return a.x[Cur] < b.x[Cur]; 41 } 42 void pushup(int rt) { 43 for (int i=0; i<DIM; ++i) { 44 if (lc) T[rt].mn[i] = min(T[rt].mn[i], T[lc].mn[i]), T[rt].mx[i] = max(T[rt].mx[i],T[lc].mx[i]); 45 if (rc) T[rt].mn[i] = min(T[rt].mn[i], T[rc].mn[i]), T[rt].mx[i] = max(T[rt].mx[i],T[rc].mx[i]); 46 } 47 } 48 void NewNode(int rt,Point p) { 49 T[rt].p = p; 50 T[rt].mn[0] = T[rt].mx[0] = p.x[0]; 51 T[rt].mn[1] = T[rt].mx[1] = p.x[1]; 52 } 53 int build(int l,int r,int cd) { 54 if (l > r) return 0; 55 int m = (l + r) >> 1,rt = m; 56 Cur = cd; nth_element(P+l, P+m, P+r+1, cmp); 57 NewNode(rt,P[m]); 58 lc = build(l, m-1, cd^1); 59 rc = build(m+1, r, cd^1); 60 pushup(rt); 61 return rt; 62 } 63 /*void Insert(Point p,int &rt,int cd) { 64 if (!rt) { 65 NewNode(rt = ++CntNode, p); return ; 66 } 67 if (p.x[cd] < T[rt].p.x[cd]) Insert(p, lc, cd^1); 68 else Insert(p, rc, cd^1); 69 pushup(rt); 70 }*/ 71 LL sqr(LL x) { 72 return x * x; 73 } 74 LL dis(Point a,Point b) { 75 return sqr(a.x[0] - b.x[0]) + sqr(a.x[1] - b.x[1]); 76 } 77 LL dist(Point a,KDtree b) { 78 LL res = 0; 79 res += max(sqr(a.x[0] - b.mn[0]), sqr(a.x[0] - b.mx[0])); 80 res += max(sqr(a.x[1] - b.mn[1]), sqr(a.x[1] - b.mx[1])); 81 return res; 82 } 83 void query(Point p,int rt) { 84 if (!rt) return ; 85 LL d = dis(T[rt].p,p); 86 if (d > q.top().dis || (d==q.top().dis && T[rt].p.id < q.top().id)) 87 q.pop(), q.push(State(d,T[rt].p.id)); 88 LL dl = lc ? dist(p,T[lc]) : 0; // --- T[rt] !!! 89 LL dr = rc ? dist(p,T[rc]) : 0; // --- T[rt] !!! 90 if (dl > dr) { 91 if (dl >= q.top().dis) query(p,lc); 92 if (dr >= q.top().dis) query(p,rc); 93 } 94 else { 95 if (dr >= q.top().dis) query(p,rc); 96 if (dl >= q.top().dis) query(p,lc); 97 } 98 } 99 int main() { 100 int n = read(); 101 for (int x,y,i=1; i<=n; ++i) { 102 P[i].x[0] = read(),P[i].x[1] = read(); 103 P[i].id = i; 104 } 105 Root = build(1,n,0); 106 int m = read(); 107 while (m--) { 108 int x = read(),y = read(),k = read(); 109 for (int i=1; i<=k; ++i) q.push(State(-INF,0)); 110 query(Point(x,y),Root); 111 printf("%d\n",q.top().id); 112 while (!q.empty()) q.pop(); 113 } 114 return 0; 115 }