BZOJ 2626 & KDtree

时间:2023-03-10 04:37:39
BZOJ 2626 & KDtree

题意:

  二维平面n个点 每次给出一个点询问距离第k小的点.

SOL:

  kdtree裸题,抄了一发别人的模板...二维割起来还是非常显然的.膜rzz的论文.

  不多说了吧....

Code:

  

/*==========================================================================
# Last modified: 2016-03-18 20:26
# Filename: 2626.cpp
# Description:
==========================================================================*/
#define me AcrossTheSky
#include <cstdio>
#include <cmath>
#include <ctime>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm> #include <set>
#include <map>
#include <stack>
#include <queue>
#include <vector> #define lowbit(x) (x)&(-x)
#define FOR(i,a,b) for((i)=(a);(i)<=(b);(i)++)
#define FORP(i,a,b) for(int i=(a);i<=(b);i++)
#define FORM(i,a,b) for(int i=(a);i>=(b);i--)
#define ls(a,b) (((a)+(b)) << 1)
#define rs(a,b) (((a)+(b)) >> 1)
#define getlc(a) ch[(a)][0]
#define getrc(a) ch[(a)][1] #define maxn 100000
#define maxm 100000
#define pi 3.1415926535898
#define _e 2.718281828459
#define INF 1070000000
using namespace std;
typedef long long LL;
typedef unsigned long long uLL; template<class T> inline
void read(T& num) {
bool start=false,neg=false;
char c;
num=0; while((c=getchar())!=EOF) {
if(c=='-') start=neg=true;
else if(c>='0' && c<='9') {
start=true;
num=num*10+c-'0';
} else if(start) break;
}
if(neg) num=-num;
}
/*==================split line==================*/
int flag;
struct node{
int id;
LL x,y;
void in(int i){
read(x); read(y);
id=i;
}
bool operator<(const node& a)const{
if(!flag) return x<a.x;
return y<a.y;
}
}p[maxn];
LL sqr(LL x){return x*x;}
LL dist(node a,node b){return sqr(a.x-b.x)+sqr(a.y-b.y);} struct cpt{
LL dis;
int id;
bool operator<(const cpt &a)const{
if(dis!=a.dis) return dis>a.dis;
return id<a.id;
}
}; priority_queue<cpt> q; struct KD{
LL minv[2],maxv[2];
LL dis(node p){
LL x=max(abs(p.x-minv[0]),abs(p.x-maxv[0]));
LL y=max(abs(p.y-minv[1]),abs(p.y-maxv[1]));
return sqr(x)+sqr(y);
}
KD operator+(const KD &a){
KD c;
c.minv[0]=min(minv[0],a.minv[0]);
c.minv[1]=min(minv[1],a.minv[1]);
c.maxv[0]=max(maxv[0],a.maxv[0]);
c.maxv[1]=max(maxv[1],a.maxv[1]);
return c;
}
}; struct KDtree{
node p;KD c;
}tree[maxn];
int n,m,kth,ch[maxn][2],tot; int build(int l,int r,int k){
int x=++tot;
flag=k;
int mid=rs(l,r); nth_element(p+l,p+mid,p+r+1);
tree[x].p=p[mid];
tree[x].c.minv[0]=tree[x].c.maxv[0]=tree[x].p.x;
tree[x].c.minv[1]=tree[x].c.maxv[1]=tree[x].p.y;
if (l<=mid-1){
ch[x][0]=build(l,mid-1,k^1);
tree[x].c=tree[x].c+tree[ch[x][0]].c;
}
if (mid+1<=r){
ch[x][1]=build(mid+1,r,k^1);
tree[x].c=tree[x].c+tree[ch[x][1]].c;
}
return x;
}
void ask(int x,node a,int k){
cpt tmp=(cpt){dist(tree[x].p,a),tree[x].p.id};
int lc=ch[x][0],rc=ch[x][1];
flag=k;
if (q.size()<kth) q.push(tmp);
else if (tmp<q.top()){q.pop(); q.push(tmp);}
if (a<tree[x].p) swap(lc,rc);
if (lc && (q.size()<kth || tree[lc].c.dis(a)>=q.top().dis))
ask(lc,a,k^1);
if (rc && (q.size()<kth || tree[rc].c.dis(a)>=q.top().dis))
ask(rc,a,k^1);
}
int main(){
//freopen("a.in","r",stdin);
read(n);
FORP(i,1,n) p[i].in(i);
build(1,n,0);
int m; read(m);
FORP(i,1,m){
node a; a.in(i);
read(kth);
while (!q.empty()) q.pop();
ask(1,a,0);
printf("%d\n",q.top().id);
}
}