2626: JZPFAR K-D tree

裸题,用堆维护一下。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;

const int N=100005;
const int INF=1000000007;
int n,D,root;
int ls[N],rs[N];

struct node
{
    int d[2],mn[2],mx[2];
    int id;
    inline int& operator[](int x)
    {
        return d[x];
    }
}tree[N],p;

struct W
{
    long long val;
    int id;
    W () {};
    W (long long _,int __) {val=_; id=__;}
};

inline bool operator<(W a,W b)
{
    return a.val==b.val?a.id<b.id:a.val>b.val;
} 

priority_queue<W> q;

inline int read()
{
    int a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}

inline bool operator<(node a,node b)
{
    return a[D]==b[D]?a[D^1]<b[D^1]:a[D]<b[D];
}

inline void pushup(int k)
{
    for (int i=0;i<=1;i++)
    {
        tree[k].mn[i]=min(tree[k].mn[i],min(tree[ls[k]].mn[i],tree[rs[k]].mn[i]));
        tree[k].mx[i]=max(tree[k].mx[i],max(tree[ls[k]].mx[i],tree[rs[k]].mx[i]));
    }
}

void build(int &k,int l,int r,int dir)
{
    int mid=l+r>>1; k=mid; D=dir;
    nth_element(tree+l,tree+mid,tree+r+1);
    tree[mid].mn[0]=tree[mid].mx[0]=tree[mid][0];
    tree[mid].mn[1]=tree[mid].mx[1]=tree[mid][1];
    if (l<mid) build(ls[k],l,mid-1,dir^1);
    if (r>mid) build(rs[k],mid+1,r,dir^1);
    pushup(k);
}

inline long long sqr(int x)
{
    return (long long)x*x;
}

inline long long dis(node a,node b)
{
    return (long long)sqr(a[0]-b[0])+(long long)sqr(a[1]-b[1]);
}

inline long long getdis(int x)
{
    if (!x) return -2;
    long long ans=0;
    for (int i=0;i<=1;i++)
        ans+=max((long long)sqr(tree[x].mx[i]-p[i]),(long long)sqr(tree[x].mn[i]-p[i]));
    return ans;
}

void query(int k)
{
    if (!k) return;
    long long dl=getdis(ls[k]),dr=getdis(rs[k]),d=dis(p,tree[k]);
    if (d>q.top().val||(d==q.top().val&&tree[k].id<q.top().id))
    {
        q.pop();
        q.push(W(d,tree[k].id));
    }
    if (dl>dr)
    {
        if (dl>=q.top().val) query(ls[k]);
        if (dr>=q.top().val) query(rs[k]);
    }
    else
    {
        if (dr>=q.top().val) query(rs[k]);
        if (dl>=q.top().val) query(ls[k]);
    }
}

int main()
{
    n=read();
    tree[0].mn[0]=tree[0].mn[1]=INF;
    tree[0].mx[0]=tree[0].mx[1]=-INF;
    for (int i=1;i<=n;i++)
        tree[i][0]=read(),tree[i][1]=read(),tree[i].id=i;
    build(root,1,n,1);
    int testcase=read();
    while (testcase--)
    {
        while (!q.empty()) q.pop();
        p[0]=read(); p[1]=read(); 
        int k=read();
        for (int i=1;i<=k;i++) q.push(W(-1,0));
        query(root);
        printf("%d\n",q.top().id);
    }
    return 0;
}       
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值