标签:tree 关系 UI 描述 距离 题目 using 点距 printf
题目描述
输入
输出
样例输入
3
0 0
0 1
0 2
3
1 1 2
0 0 3
0 1 1
样例输出
3
1
1
题解
KD-tree+堆
求与一个点距离第k大的方法:维护一个k个元素的小根堆,表示距离,初始都为极小值;然后对于每个点,如果距离比堆顶元素大,则将堆顶元素替换为该距离;并根据左右子树的估价函数与堆顶元素的大小关系决定是否向下查询。
然而本题中要求距离相同的编号较小者距离较大,所以我们在以距离为第一关键字维护小根堆的同时以编号第二关键字维护大根堆即可。
注意在估价与堆顶相等时也要向下查询,因为可能存在编号的问题。
#include <queue> #include <cstdio> #include <cstring> #include <utility> #include <algorithm> #define squ(x) (ll)(x) * (x) #define N 100010 using namespace std; typedef long long ll; priority_queue<pair<ll , int> > q; struct data { int p[2] , mx[2] , mn[2] , id , c[2]; }a[N]; int d , root , num; bool cmp(data a , data b) { return a.p[d] == b.p[d] ? a.p[d ^ 1] < b.p[d ^ 1] : a.p[d] < b.p[d]; } void pushup(int k , int x) { a[k].mx[0] = max(a[k].mx[0] , a[x].mx[0]); a[k].mn[0] = min(a[k].mn[0] , a[x].mn[0]); a[k].mx[1] = max(a[k].mx[1] , a[x].mx[1]); a[k].mn[1] = min(a[k].mn[1] , a[x].mn[1]); } int build(int l , int r , int now) { int mid = (l + r) >> 1; d = now , nth_element(a + l , a + mid , a + r + 1 , cmp); a[mid].mx[0] = a[mid].mn[0] = a[mid].p[0]; a[mid].mx[1] = a[mid].mn[1] = a[mid].p[1]; if(l < mid) a[mid].c[0] = build(l , mid - 1 , now ^ 1) , pushup(mid , a[mid].c[0]); if(r > mid) a[mid].c[1] = build(mid + 1 , r , now ^ 1) , pushup(mid , a[mid].c[1]); return mid; } ll getdis(int k , int x , int y) { return max(squ(a[k].mx[0] - x) , squ(a[k].mn[0] - x)) + max(squ(a[k].mx[1] - y) , squ(a[k].mn[1] - y)); } void query(int k , int x , int y) { ll dn = squ(a[k].p[0] - x) + squ(a[k].p[1] - y) , dl = (a[k].c[0] ? getdis(a[k].c[0] , x , y) : -1) , dr = (a[k].c[1] ? getdis(a[k].c[1] , x , y) : -1); if(make_pair(-dn , a[k].id) < q.top()) q.pop() , q.push(make_pair(-dn , a[k].id)); if(dl > dr) { if(dl >= -q.top().first) query(a[k].c[0] , x , y); if(dr >= -q.top().first) query(a[k].c[1] , x , y); } else { if(dr >= -q.top().first) query(a[k].c[1] , x , y); if(dl >= -q.top().first) query(a[k].c[0] , x , y); } } int main() { int n , i , m , x , y , k; scanf("%d" , &n); for(i = 1 ; i <= n ; i ++ ) scanf("%d%d" , &a[i].p[0] , &a[i].p[1]) , a[i].id = i; root = build(1 , n , 0); scanf("%d" , &m); while(m -- ) { scanf("%d%d%d" , &x , &y , &k); while(!q.empty()) q.pop(); for(i = 1 ; i <= k ; i ++ ) q.push(make_pair(0 , 1 << 30)); query(root , x , y); printf("%d\n" , q.top().second); } return 0; }
标签:tree 关系 UI 描述 距离 题目 using 点距 printf
原文地址:http://www.cnblogs.com/GXZlegend/p/7190354.html