• [bzoj4520][Cqoi2016]K远点对_KD-Tree_堆


    K远点对 bzoj-4520 Cqoi-2016

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

    注释:$1le nle 10^5$,$1le kle 100$,$kle n*(n-1)/2$,$0le x,y<2^{31}$。


    想法

    KD-Tree还是很暴力的。

    我们只需要考虑直接暴力的维护一个个数为$k$的堆即可。

    复杂度什么的都滚蛋吧,反正能过。

    Code

    #include <bits/stdc++.h>
    #define inf 10000000000000000ll 
    #define N 100010 
    using namespace std; typedef long long ll;
    char *p1,*p2,buf[100000]; int d,root;
    #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
    int rd() {int x=0; char c=nc(); while(c<48) c=nc(); while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x;}
    priority_queue<ll,vector<ll>,greater<ll> >q;
    struct Node {int p[2],ls,rs,mn[2],mx[2];}a[N];
    inline bool cmp(const Node &a,const Node &b) {return a.p[d]==b.p[d]?a.p[d^1]<b.p[d^1]:a.p[d]<b.p[d];}
    template <typename T> void Max(T &x,T y) {x=max(x,y);}
    template <typename T> void Min(T &x,T y) {x=min(x,y);}
    inline void pushup(int x,int k)
    {
    	Max(a[x].mx[0],a[k].mx[0]); Max(a[x].mx[1],a[k].mx[1]);
    	Min(a[x].mn[0],a[k].mn[0]); Min(a[x].mn[1],a[k].mn[1]);
    }
    int build(int l,int r,int now)
    {
    	int mid=(l+r)>>1;
    	d=now; nth_element(a+l,a+mid,a+r+1,cmp);
    	a[mid].mn[0]=a[mid].mx[0]=a[mid].p[0];
    	a[mid].mn[1]=a[mid].mx[1]=a[mid].p[1];
    	if(l<mid) a[mid].ls=build(l,mid-1,now^1),pushup(mid,a[mid].ls);
    	if(mid<r) a[mid].rs=build(mid+1,r,now^1),pushup(mid,a[mid].rs);
    	return mid;
    }
    inline ll sqr(ll x) {return x*x;}
    inline ll getdis(int x,int p0,int p1) {return sqr(max(abs(p0-a[x].mx[0]),abs(p0-a[x].mn[0])))+sqr(max(abs(p1-a[x].mn[1]),abs(p1-a[x].mx[1])));}
    void query(int x,int k)
    {
    	int ls=a[x].ls,rs=a[x].rs; ll dl,dr;
    	dl=ls?getdis(ls,a[k].p[0],a[k].p[1]):-inf;
    	dr=rs?getdis(rs,a[k].p[0],a[k].p[1]):-inf;
    	ll dis=sqr(a[k].p[0]-a[x].p[0])+sqr(a[k].p[1]-a[x].p[1]);
    	if(dis>q.top()&&x!=k) q.pop(),q.push(dis);
    	if(dl>dr)
    	{
    		if(dl>q.top()) query(ls,k);
    		if(dr>q.top()) query(rs,k);
    	}
    	else
    	{
    		if(dr>q.top()) query(rs,k);
    		if(dl>q.top()) query(ls,k);
    	}
    }
    int main()
    {
    	int n=rd(),m=rd(); m*=2;
    	for(int i=1;i<=n;i++) a[i].p[0]=rd(),a[i].p[1]=rd();
    	root=build(1,n,0);
    	for(int i=1;i<=m;i++) q.push(0);
    	for(int i=1;i<=n;i++) query(root,i);
    	cout << q.top() << endl ;
    	return 0;
    }
    

    小结:好题。

  • 相关阅读:
    java中高级软件工程师面试总结
    失败的面试经历
    解决webstorm打开包含node_modules项目卡死问题
    通俗易懂的理解javascript闭包
    javascript实现silverlight pivotViewer控件
    javascript面向对象
    吐槽一下万网空间
    html5的Canvas
    前端CSS兼容的一些思路
    Win10 Ubuntu子系统访问Windows目录
  • 原文地址:https://www.cnblogs.com/ShuraK/p/10239026.html
Copyright © 2020-2023  润新知