zoukankan      html  css  js  c++  java
  • [bzoj][Cqoi2016]K远点对【堆】【KD-tree】

    【题目描述】

    Description

    已知平面内 N 个点的坐标,求欧氏距离下的第 K 远点对。

    Input

    输入文件第一行为用空格隔开的两个整数 N, K。接下来 N 行,每行两个整数 X,Y,表示一个点
    的坐标。1 < =  N < =  100000, 1 < =  K < =  100, K < =  N*(N−1)/2 , 0 < =  X, Y < 2^31。

    Output

    输出文件第一行为一个整数,表示第 K 远点对的距离的平方(一定是个整数)。

    Sample Input

    10 5
    0 0
    0 1
    1 0
    1 1
    2 0
    2 1
    1 2
    0 2
    3 0
    3 1

    Sample Output

    9

    HINT

    Source

    【题解】

     KD-tree裸题

    用小根堆维护当前答案,query判断范围时与堆顶元素比较

    /* --------------
        user Vanisher
        problem bzoj-4520
    ----------------*/
    # include <bits/stdc++.h>
    # define 	ll 		long long
    # define 	inf 	6e9
    # define 	N 		100010
    using namespace std;
    priority_queue <ll,vector<ll>,greater<ll> > hp;
    ll read(){
    	ll tmp=0, fh=1; char ch=getchar();
    	while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
    	while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
    	return tmp*fh;
    }
    struct point{
    	ll x,y;
    }p[N];
    struct node{
    	ll lx,ly,rx,ry,pl,pr,tag;
    	point num;
    }T[N];
    ll place,n,k;
    double sqr(double x){return x*x;}
    void change(ll now){
    	T[now].lx=min(T[now].num.x,min(T[T[now].pl].lx,T[T[now].pr].lx));
    	T[now].rx=max(T[now].num.x,max(T[T[now].pl].rx,T[T[now].pr].rx));
    	T[now].ly=min(T[now].num.y,min(T[T[now].pl].ly,T[T[now].pr].ly));
    	T[now].ry=max(T[now].num.y,max(T[T[now].pl].ry,T[T[now].pr].ry));
    }
    bool cmpx(point x, point y){return x.x<y.x;}
    bool cmpy(point x, point y){return x.y<y.y;}
    ll build(ll l, ll r){
    	if (l>r) return 0;
    	ll now=++place,mid=(l+r)/2;
    	double sumx=0,sumy=0,deltax=0,deltay=0;
    	for (ll i=l; i<=r; i++) 
    		sumx=sumx+p[i].x, sumy=sumy+p[i].y;
    	sumx=sumx/(r-l+1); sumy=sumy/(r-l+1);
    	for (ll i=l; i<=r; i++){
    		deltax=deltax+sqr(p[i].x-sumx);
    		deltay=deltay+sqr(p[i].y-sumy);
    	}	
    	if (deltax>deltay){
    		T[now].tag=0;
    		nth_element(p+l,p+mid,p+r+1,cmpx);
    	}
    	else{
    		T[now].tag=1;
    		nth_element(p+l,p+mid,p+r+1,cmpy);
    	} 
    	T[now].num=p[mid];
    	T[now].pl=build(l,mid-1); T[now].pr=build(mid+1,r);
    	change(now);
    	return now;
    }
    ll distmx(ll now, point x){
    	ll num=sqr(max(abs(T[now].lx-x.x),abs(T[now].rx-x.x)));
    	num=num+sqr(max(abs(T[now].ly-x.y),abs(T[now].ry-x.y)));
    	return num;
    }
    void solve(ll now, point x){
    	if (now==0) return;
    	ll d0=sqr(T[now].num.x-x.x)+sqr(T[now].num.y-x.y),d1,d2;
    	if (d0>hp.top()){
    		hp.pop(); hp.push(d0);
    	}
    	if (T[now].pl!=0) d1=distmx(T[now].pl,x); else d1=-1;
    	if (T[now].pr!=0) d2=distmx(T[now].pr,x); else d2=-1;
    	if (d1>d2){
    		if (d1>hp.top()) solve(T[now].pl,x);
    		if (d2>hp.top()) solve(T[now].pr,x); 
    	}
    	else {
    		if (d2>hp.top()) solve(T[now].pr,x);
    		if (d1>hp.top()) solve(T[now].pl,x);
    	}
    }
    int main(){
    	n=read(); k=read();
    	T[0].ly=T[0].lx=inf; T[0].rx=T[0].ry=-inf;
    	for (ll i=1; i<=2*k; i++) hp.push(-1);
    	for (ll i=1; i<=n; i++)
    		p[i].x=read(), p[i].y=read();
    	ll rt=build(1,n);
    	for (ll i=1; i<=n; i++)
    		solve(rt,p[i]);
    	printf("%lld
    ",hp.top());
    	return 0;
    }
    


  • 相关阅读:
    5059 一起去打CS
    2439 降雨量
    vijos P1037搭建双塔
    4979 数塔
    2596 售货员的难题
    P2342 叠积木
    1540 银河英雄传说
    1051 接龙游戏
    hdu1251
    洛谷P1717 钓鱼
  • 原文地址:https://www.cnblogs.com/Vanisher/p/9136045.html
Copyright © 2011-2022 走看看