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);
	}
}

 

posted @ 2016-03-19 14:12  YCuangWhen  阅读(296)  评论(0编辑  收藏  举报