JZPFAR(K-D Tree + 第K遠點)

JZPFAR

題意:

給定平面上NN個點,然後MM個詢問:給定一個點,求第KK遠點。

思路: KK遠點對的弱化版本?

  1. 建好普通的K-D Tree
  2. 每次詢問維護一個大小爲KK的小頂堆即可
  3. 剪枝也非常基礎

代碼

#include "bits/stdc++.h"
#define hhh printf("hhh\n")
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
using namespace std;
typedef long long ll;
typedef pair<ll,int> pr;
inline int read() {int x=0,f=1;char c=getchar();while(c!='-'&&(c<'0'||c>'9'))c=getchar();if(c=='-')f=-1,c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return f*x;}

const int maxn = 1e5+10;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const double eps = 1e-7;

int n, m, tot, Dim, rt;
int ls[maxn], rs[maxn];
int mi[maxn][2], mx[maxn][2], sz[maxn];

inline ll square(int x) { return ll(x)*x; }

struct P{
    int x[2], id;
    friend bool operator < (const P &a, const P &b) {
        return a.x[Dim]<b.x[Dim];
    }
    inline ll dis(const P &rhs) const {
        return square(x[0]-rhs.x[0])+square(x[1]-rhs.x[1]);
    }
}p[maxn], tmp[maxn], q;

priority_queue<pr,vector<pr>,greater<pr> > Q;

inline void Max(int &x, int y) { if(x<y) x=y; }
inline void Min(int &x, int y) { if(x>y) x=y; }

void push_up(int now) {
    for(int i=0; i<2; ++i) {
        mi[now][i]=mx[now][i]=p[now].x[i];
        if(ls[now]) Min(mi[now][i],mi[ls[now]][i]), Max(mx[now][i],mx[ls[now]][i]);
        if(rs[now]) Min(mi[now][i],mi[rs[now]][i]), Max(mx[now][i],mx[rs[now]][i]);
    }
    sz[now]=sz[ls[now]]+sz[rs[now]]+1;
}

void build(int l, int r, int dim, int &now) {
    if(l>r) { now=0; return; }
    now=++tot;
    int m=(l+r)/2;
    Dim=dim; nth_element(tmp+l,tmp+m,tmp+r+1); p[now]=tmp[m];
    build(l,m-1,dim^1,ls[now]); build(m+1,r,dim^1,rs[now]);
    push_up(now);
}

inline ll cal(int now) {
    return max(square(mi[now][0]-q.x[0]),square(mx[now][0]-q.x[0]))+max(square(mi[now][1]-q.x[1]),square(mx[now][1]-q.x[1]));
}

void query(int now) {
    if(!now) return;
    ll d0=q.dis(p[now]);
    if(pr(d0,-p[now].id)>Q.top()) Q.pop(), Q.push(pr(d0,-p[now].id));
    int l=ls[now], r=rs[now];
    ll dl=cal(l), dr=cal(r);
    if(dl<dr) swap(l,r), swap(dl,dr);
    if(dl>=Q.top().first) query(l);
    if(dr>=Q.top().first) query(r);
}

int main() {
    n=read();
    for(int i=1; i<=n; ++i) {
        scanf("%d%d", &tmp[i].x[0], &tmp[i].x[1]);
        tmp[i].id=i;
    }
    build(1,n,0,rt);
    m=read();
    while(m--) {
        scanf("%d%d", &q.x[0], &q.x[1]);
        int k=read();
        while(Q.size()) Q.pop();
        for(int i=0; i<k; ++i) Q.push(pr(0,-inf));
        query(rt);
        printf("%d\n", -Q.top().second);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章