zoukankan      html  css  js  c++  java
  • #K-D Tree#洛谷 2093 [国家集训队]JZPFAR

    题目

    平面上有 (n) 个点。现在有 (m) 次询问,每次给定一个点 ((px, py)) 和一个整数 (k)
    输出 (n) 个点中离 ((px, py)) 的距离第 (k) 大的点的标号。
    如果有两个(或多个)点距离 ((px, py)) 相同,那么认为标号较小的点距离较大。


    分析

    考虑用K-D Tree实现,维护区间横纵坐标最小值最大值,
    至于第(k)远点对开一个大小为(k)的小根堆初始为极小值,
    每次将最小的替换出去即可,注意还要比较标号


    代码

    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #include <queue>
    #define rr register
    using namespace std;
    const int N=200011;
    typedef long long lll;
    int ran,root,n,k;
    struct Two{
    	lll w; int rk;
    	bool operator >(const Two &t)const{
    	    return w>t.w||(w==t.w&&rk<t.rk);
    	}
    	bool operator <(const Two &t)const{
    	    return w>t.w||(w==t.w&&rk<t.rk);
    	}
    };
    priority_queue<Two>q;
    inline signed iut(){
    	rr int ans=0,f=1; rr char c=getchar();
    	while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans*f;
    }
    inline void print(int ans){
    	if (ans<0) putchar('-'),ans=-ans;
    	if (ans>9) print(ans/10);
    	putchar(ans%10+48);
    }
    inline signed min(int a,int b){return a<b?a:b;}
    inline lll max(lll a,lll b){return a>b?a:b;}
    struct rec{
    	int p[3];
    	bool operator <(const rec &t)const{
    	    return p[ran]<t.p[ran];
    	}
    };
    inline lll SQR(lll x){return x*x;}
    struct KD_Tree{
    	int mn[N][2],mx[N][2],son[N][2]; rec p[N];
    	inline void pup(int now){
    		for (rr int i=0;i<2;++i){
    			mn[now][i]=mx[now][i]=p[now].p[i];
    			if (son[now][0]){
    				mn[now][i]=min(mn[now][i],mn[son[now][0]][i]);
    				mx[now][i]=max(mx[now][i],mx[son[now][0]][i]);
    			}
    			if (son[now][1]){
    				mn[now][i]=min(mn[now][i],mn[son[now][1]][i]);
    				mx[now][i]=max(mx[now][i],mx[son[now][1]][i]);
    			}
    		}
    	}
    	inline signed build(int l,int r,int Ran){
    		if (l>r) return 0;
    		rr int mid=(l+r)>>1;
    		ran=Ran,nth_element(p+l,p+mid,p+1+r);
    		son[mid][0]=build(l,mid-1,Ran^1);
    		son[mid][1]=build(mid+1,r,Ran^1);
    		pup(mid);
    		return mid;
    	}
    	inline lll calc(int t,int x){
    		return max(SQR(p[x].p[0]-mn[t][0]),SQR(p[x].p[0]-mx[t][0]))+max(SQR(p[x].p[1]-mn[t][1]),SQR(p[x].p[1]-mx[t][1]));
    	}
    	inline void query(int now,int x){
    		rr Two t=(Two){SQR(p[x].p[0]-p[now].p[0])+SQR(p[x].p[1]-p[now].p[1]),p[now].p[2]};
    		if (t>q.top()) q.pop(),q.push(t);
    		rr Two c0=(Two){calc(son[now][0],x),0};
    		rr Two c1=(Two){calc(son[now][1],x),0};
    		if (son[now][0]&&son[now][1]){
    			if (c0>c1&&c0>q.top()){
    				query(son[now][0],x);
    				if (c1>q.top()) query(son[now][1],x);
    			}else if (c1>q.top()){
    				query(son[now][1],x);
    				if (c0>q.top()) query(son[now][0],x);
    			}
    		}else if (son[now][0]){
    			if (c0>q.top()) query(son[now][0],x);
    		}else if (son[now][1]){
    			if (c1>q.top()) query(son[now][1],x);
    		}
    	}
    }Tre;
    signed main(){
    	n=iut();
    	for (rr int i=1;i<=n;++i) Tre.p[i].p[0]=iut(),Tre.p[i].p[1]=iut(),Tre.p[i].p[2]=i;
    	root=Tre.build(1,n,0);
    	for (rr int m=iut();m;--m){
    		Tre.p[n+1].p[0]=iut(),Tre.p[n+1].p[1]=iut();
    		while (!q.empty()) q.pop();
    		for (rr int kth=iut();kth;--kth)
    		    q.push((Two){-1000000000000000000ll,0});
    		Tre.query(root,n+1),print(q.top().rk),putchar(10);
    	}
    	return 0;
    }
    
  • 相关阅读:
    SQlite数据库
    关于如何获取剪切板的多个图片处理
    aes 和 Md5 分析
    SIP消息
    getItemAt
    C++ map的方法
    C++ 解析Json
    CentOS 6.3安装配置LAMP服务器(Apache+PHP5+MySQL)
    阿里云服务器CentOS 5.7(64位)安装配置LAMP服务器(Apache+PHP5+MySQL)
    Apache虚拟主机(vhost)配置教程
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/14911948.html
Copyright © 2011-2022 走看看