[国家集训队]JZPFAR
分析
一次过,非常爽。考虑 上的最近邻查询。虽然有人已经证明 上的最近邻查询时间复杂度会被构造数据卡到 。但是多数情况下是非常快的。那么这道题,只是把最近邻换成第 大距离。我们只需要用个堆来动态维护一下就好了。注意因为有编号的问题,所以要注意查询的小细节。
代码
#include<bits/stdc++.h> using namespace std; #define int long long int read() { int x = 0,f = 0;char ch = getchar(); while(!isdigit(ch)) {if(ch == '-')f = 1;ch = getchar();} while(isdigit(ch)) {x = x * 10 + ch - '0';ch = getchar();} return f ? -x : x; } const int N = 1e5 + 100; #define Pair pair<int,int> struct Point{int p[2],id;}A[N]; bool cmp0(Point a,Point b) {return a.p[0] < b.p[0];} bool cmp1(Point a,Point b) {return a.p[1] < b.p[1];} struct Node{ int mx[2],mi[2],p[2],ch[2],id; }t[N]; int n,size,rt; void pushup(int u) { int lc = t[u].ch[0],rc = t[u].ch[1]; for(int i = 0;i < 2;i++) { t[u].mx[i] = t[u].mi[i] = t[u].p[i]; if(lc) { t[u].mx[i] = max(t[u].mx[i],t[lc].mx[i]); t[u].mi[i] = min(t[u].mi[i],t[lc].mi[i]); } if(rc) { t[u].mx[i] = max(t[u].mx[i],t[rc].mx[i]); t[u].mi[i] = min(t[u].mi[i],t[rc].mi[i]); } } } int build(int l,int r,int tpye) { if(r < l) return 0; int mid = l + r >> 1; if(tpye) nth_element(A+l,A+mid,A+r+1,cmp1); else nth_element(A+l,A+mid,A+r+1,cmp0); int u = ++size; t[u].p[0] = A[mid].p[0];t[u].p[1] = A[mid].p[1];t[u].id = A[mid].id; t[u].ch[0] = build(l,mid-1,1 - tpye); t[u].ch[1] = build(mid+1,r,1 - tpye);pushup(u); return u; } const int inf = 1e9; priority_queue<Pair,vector<Pair>,greater<Pair> > heap; int pow2(int x) {return x * x;} int dist(int u,Point x) { if(!u) return -inf; int P1 = pow2(t[u].mx[0] - x.p[0]); int P2 = pow2(t[u].mi[0] - x.p[0]); int P3 = pow2(t[u].mx[1] - x.p[1]); int P4 = pow2(t[u].mi[1] - x.p[1]); return max(P1,P2) + max(P3,P4); } int dist(int x,int y,Point b) { return pow2(x-b.p[0]) + pow2(y-b.p[1]); } void ask(int u,Point x) { if(!u) return; int dis = dist(t[u].p[0],t[u].p[1],x); if(heap.top() < Pair(dis,-t[u].id)) heap.pop(),heap.push(Pair(dis,-t[u].id)); int disl = dist(t[u].ch[0],x),disr = dist(t[u].ch[1],x); if(disl > disr) { if(disl >= heap.top().first) ask(t[u].ch[0],x); if(disr >= heap.top().first) ask(t[u].ch[1],x); } else { if(disr >= heap.top().first) ask(t[u].ch[1],x); if(disl >= heap.top().first) ask(t[u].ch[0],x); } } void print(int x) { if(!x) return; cout << x <<" "<<t[x].mi[0] <<" "<<t[x].mx[0] <<" "<<t[x].mi[1]<<" "<<t[x].mx[1]<< endl; print(t[x].ch[0]);print(t[x].ch[1]); } signed main() { n = read(); for(int i = 1;i <= n;i++) A[i].p[0] = read(),A[i].p[1] = read(),A[i].id = i; rt = build(1,n,0); //print(rt); int m = read(); while(m--) { while(heap.size()) heap.pop(); int x = read(),y = read(),k = read(); for(int i = 1;i <= k;i++) heap.push(Pair(-1,0)); ask(rt,(Point){x,y}); printf("%lld\n", -heap.top().second); } }