• KDtree


    KDT

    为多维的点构造相对平衡的二叉树结构(空间划分)

    原理:每次按照某维排序(可以按顺序依次,也可随机,貌似按方差大的维更优),取中间点作为当前点,递归左右区间


    时间复杂度(O(n^{1-frac1w}),w)为维度

    题意:求平面上第K远点对的距离

    (N100000K100)

    //K-D tree 
    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    	return f==1?x:-x;
    }
    #define ll long long
    const int N=1e5+4;
    const ll inf=1e18;
    struct pnt{int x[2];}g[N];
    inline ll sqr(int x){return (ll)x*x;}//long long!!!
    inline int get(int l,int r){//找方差最大的最优 
    	double ax=0,ay=0,bx=0,by=0,mod=r-l+1;
    	for(int i=l;i<=r;i++){
    		ax+=g[i].x[0];bx+=g[i].x[1];
    		ay+=sqr(g[i].x[0]);by+=sqr(g[i].x[1]);
    	}
    	ax=ay*mod-ax*ax;bx=by*mod-bx*bx;
    	if(ax>bx)return 0;
    	return 1; 
    }
    int opt,n,k;
    inline bool cmp(const pnt &y,const pnt &z){
    	return y.x[opt]<z.x[opt];
    } 
    priority_queue<ll>q;
    #define lc L[p]
    #define rc R[p]
    #define max_(a,b) (a>b?a:b)
    #define min_(a,b) (a>b?b:a)
    struct K_D_tree{
    	int mx[N<<1][2],mn[N<<1][2],L[N<<1],R[N<<1],cnt=0;
    	pnt d[N<<1];
    	inline void pushup(int p){
    		for(int i=0;i<2;i++)mx[p][i]=mn[p][i]=d[p].x[i];
    		if(lc)for(int i=0;i<2;i++){
    			mx[p][i]=max_(mx[p][i],mx[lc][i]);
    			mn[p][i]=min_(mn[p][i],mn[lc][i]);
    		}
    		if(rc)for(int i=0;i<2;i++){
    			mx[p][i]=max_(mx[p][i],mx[rc][i]);
    			mn[p][i]=min_(mn[p][i],mn[rc][i]);
    		}
    	}
    	inline void build(int &p,int l,int r){
    		if(l>r)return;
    		p=++cnt;
    		int mid=l+r>>1;
    		opt=get(l,r);//切换维度
    		nth_element(g+l,g+mid,g+r+1,cmp);//把mid小的放在mid位置处,大的放后面,小的放前面 
    		d[p]=g[mid];
    		build(lc,l,mid-1);build(rc,mid+1,r);
    		pushup(p); 
    	}
    	inline ll calc(pnt a,pnt b){
    		return sqr(a.x[0]-b.x[0])+sqr(a.x[1]-b.x[1]);
    	}
    	inline ll deal(pnt a,int b){//所在子树可能最远的点 
    		return max_(sqr(a.x[0]-mx[b][0]),sqr(a.x[0]-mn[b][0]))+max_(sqr(a.x[1]-mx[b][1]),sqr(a.x[1]-mn[b][1]));
    	}
    	inline void query(int p,pnt y){//最坏sqrt(n) 最优logn^2 
    		ll dl=-inf,dr=-inf;
    		if(lc)dl=deal(y,lc);
    		if(rc)dr=deal(y,rc);
    		ll di=calc(y,d[p]);
    		if(-q.top()<di){q.pop();q.push(-di);}//找到了更大的点
    		if(dl>dr){
    			if(-q.top()<dl)query(lc,y);
    			if(-q.top()<dr)query(rc,y);
    		} 
    		else{
    			if(-q.top()<dr)query(rc,y);
    			if(-q.top()<dl)query(lc,y); 
    		}
    	}
    }T; 
    int main(){
    	srand(time(0));
    	n=read();k=read();
    	for(int i=1;i<=n;i++){g[i].x[0]=read();g[i].x[1]=read();} 
    	for(int i=1;i<=(k<<1);i++)q.push(0);
    	T.build(T.L[0],1,n);
    	for(int i=1;i<=n;i++)T.query(1,g[i]);
    	printf("%lld
    ",-q.top());
    	return (0-0);
    }
    
  • 相关阅读:
    通过windows server使用frp软件实现内网穿透
    【Java】使用线程解决生产者与消费者问题
    WindowsServers2019摄像头不可用的解决方案
    【CSS】复杂三栏布局
    【Java】TCP发送与接收数据
    【Java】UDP发送数据与接收数据
    【CSS】三栏布局
    【CSS】实现两栏布局
    JS获取url参数
    Centos 安装Tcl
  • 原文地址:https://www.cnblogs.com/aurora2004/p/12568932.html
Copyright © 2020-2023  润新知