zoukankan      html  css  js  c++  java
  • BZOJ 4520: [Cqoi2016]K远点对

    KD-Tree暴力大法吼哇!

    容易发现如果我们给每个点求出(K)个最远距离,放在一起找出其中的第(2K)大的就是答案(一对点会算两次)

    考虑搞出一个小根堆,刚开始往里面放(2K)(0)。然后我们枚举每个点,不断地找出距离它的最远点然后和堆顶比较,如果大于就替换掉堆顶

    最后答案就是堆顶,而这种做法正确性显然且有一定剪枝,但复杂度是(O(n^2))级别的

    然后我们就KD-Tree来实现暴力的过程即可(滑稽),复杂度(O( ext{玄学})),实测最慢跑了70ms。。。

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #define RI register int
    #define CI const int&
    using namespace std;
    typedef long long LL;
    const int N=100005; const LL INF=1e18;
    int D; priority_queue < LL,vector <LL>,greater <LL> > hp;
    struct point
    {
    	int d[2];
    	friend inline bool operator < (const point& A,const point& B)
    	{
    		return A.d[D]==B.d[D]?A.d[D^1]<B.d[D^1]:A.d[D]<B.d[D];
    	}
    }a[N],s; int n,k,rt;
    inline LL dist(const point& A,const point& B)
    {
    	return 1LL*(A.d[0]-B.d[0])*(A.d[0]-B.d[0])+1LL*(A.d[1]-B.d[1])*(A.d[1]-B.d[1]);
    }
    class KD_Tree
    {
    	private:
    		struct kd_interval
    		{
    			int ch[2]; point p,mi,mx;
    		}node[N]; int tot;
    		#define lc(x) node[x].ch[0]
    		#define rc(x) node[x].ch[1]
    		#define P(x) node[x].p
    		#define Mi(x) node[x].mi
    		#define Mx(x) node[x].mx
    		inline void pushup(CI x,CI y)
    		{
    			for (RI i=0;i<2;++i) Mi(x).d[i]=min(Mi(x).d[i],Mi(y).d[i]),
    			Mx(x).d[i]=max(Mx(x).d[i],Mx(y).d[i]);
    		}
    		inline LL getmax(CI now)
    		{
    			if (!now) return -INF; LL cur=-INF;
    			cur=max(cur,dist((point){Mi(now).d[0],Mi(now).d[1]},s));
    			cur=max(cur,dist((point){Mi(now).d[0],Mx(now).d[1]},s));
    			cur=max(cur,dist((point){Mx(now).d[0],Mi(now).d[1]},s));
    			cur=max(cur,dist((point){Mx(now).d[0],Mx(now).d[1]},s)); return cur;
    		}
    	public:
    		inline void build(int& now,CI l=1,CI r=n,CI d=0)
    		{
    			now=++tot; int mid=l+r>>1; D=d; nth_element(a+l+1,a+mid+1,a+r+1);
    			P(now)=Mi(now)=Mx(now)=a[mid];
    			if (l!=mid) build(lc(now),l,mid-1,d^1),pushup(now,lc(now));
    			if (r!=mid) build(rc(now),mid+1,r,d^1),pushup(now,rc(now));
    		}
    		inline void querymax(CI now)
    		{
    			if (!now) return; if (getmax(now)<hp.top()) return;
    			LL tp=dist(s,P(now)); if (tp>hp.top()) hp.pop(),hp.push(tp);
    			LL ml=getmax(lc(now)),mr=getmax(rc(now));
    			if (ml>mr) querymax(lc(now)),querymax(rc(now));
    			else querymax(rc(now)),querymax(lc(now));
    		}
    		#undef lc
    		#undef rc
    		#undef P
    		#undef Mi
    		#undef Mx
    }KD;
    int main()
    {
    	RI i; for (scanf("%d%d",&n,&k),i=1;i<=n;++i) scanf("%d%d",&a[i].d[0],&a[i].d[1]);
    	for (KD.build(rt),i=1;i<=2*k;++i) hp.push(0); for (i=1;i<=n;++i)
    	s=(point){a[i].d[0],a[i].d[1]},KD.querymax(rt); return printf("%lld",hp.top()),0;
    }
    
  • 相关阅读:
    7 文件操作
    初识字典1
    软件工程学习进度
    AAAA
    软件工程期末总结
    【操作系统】实验四 主存空间的分配和回收 截止提交时间:2016.6.17
    约教网站开发(一)
    操作系统实验三
    .Scrum团队成立
    数学精灵改进
  • 原文地址:https://www.cnblogs.com/cjjsb/p/12250474.html
Copyright © 2011-2022 走看看