zoukankan      html  css  js  c++  java
  • 【BZOJ4520】[CQOI2016] K远点对(KD-Tree)

    点此看题面

    大致题意: 求平面内第(k)远点对欧几里得距离的平方。

    大致思路

    我觉得可以先去看看这题:【BZOJ1941】[SDOI2010] Hide and Seek。和本题相比还要多求一个最小值。。。

    根据上面这道题的思想,我们枚举一个起点,然后在(KD-Tree)中询问前(k)大的距离。

    考虑开一个小根堆,初始状态下里面放上(2k)(0)(之所以是(2k),因为一条路径会分别以两个端点为起点计算两次)。

    我们每次只需把当前距离和小根堆堆顶比较,就能判断这一距离是否能产生贡献了。

    其余部分以及具体实现和上面这题基本差不多。(实际上我懒得再打一遍,就直接把上面的代码复制下来稍微改了改。。。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 100000
    #define LL long long
    using namespace std;
    int n,k,D;priority_queue<LL,vector<LL>,greater<LL> > Q;
    struct Point
    {
    	int x[2];I int operator [] (CI d) Con {return x[d];}
    	I bool operator < (Con Point& o) Con {return x[D]^o.x[D]?x[D]<o.x[D]:x[D^1]<o.x[D^1];}
    }p[N+5];
    class FastIO
    {
    	private:
    		#define FS 100000
    		#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
    		#define D isdigit(c=tc())
    		char c,*A,*B,FI[FS];
    	public:
    		I FastIO() {A=B=FI;}
    		Tp I void read(Ty& x) {x=0;W(!D);W(x=(x<<3)+(x<<1)+(c&15),D);}
    		#undef D
    }F;
    class KDTree//KD-Tree
    {
    	private:
    		#define Gmax(A,B) (A[0]<B[0]&&(A.x[0]=B[0]),A[1]<B[1]&&(A.x[1]=B[1]))
    		#define Gmin(A,B) (A[0]>B[0]&&(A.x[0]=B[0]),A[1]>B[1]&&(A.x[1]=B[1]))
    		#define PU(x)
    		(
    			Mx(x)=V(x),S(x,0)&&Gmax(Mx(x),Mx(S(x,0))),S(x,1)&&Gmax(Mx(x),Mx(S(x,1))),
    			Mn(x)=V(x),S(x,0)&&Gmin(Mn(x),Mn(S(x,0))),S(x,1)&&Gmin(Mn(x),Mn(S(x,1)))
    		)//上传信息
    		int rt,Nt;struct node
    		{
    			#define V(x) O[x].Val
    			#define S(x,d) O[x].Son[d]
    			#define Mx(x) O[x].Max
    			#define Mn(x) O[x].Min
    			int Son[2];Point Val,Max,Min;
    		}O[N+5];
    		I void Build(CI l,CI r,int& rt,Point *P,CI d=0)//建树
    		{
    			int mid=l+r>>1;D=d,nth_element(P+l+1,P+mid+1,P+r+1),V(rt=++Nt)=P[mid],
    			l<mid?(Build(l,mid-1,S(rt,0),P,d^1),0):(S(rt,0)=0),
    			r>mid?(Build(mid+1,r,S(rt,1),P,d^1),0):(S(rt,1)=0),PU(rt);
    		}
    		#define D(A,B) (1LL*(A[0]-B[0])*(A[0]-B[0])+1LL*(A[1]-B[1])*(A[1]-B[1]))//两点间的欧几里得距离的平方
    		#define MxD(x,P)
    			max(1LL*(P[0]-Mn(x)[0])*(P[0]-Mn(x)[0]),1LL*(P[0]-Mx(x)[0])*(P[0]-Mx(x)[0]))+
    			max(1LL*(P[1]-Mn(x)[1])*(P[1]-Mn(x)[1]),1LL*(P[1]-Mx(x)[1])*(P[1]-Mx(x)[1]))//最大距离
    		I void Max(CI rt,Con Point& P)//询问子树更新堆的答案
    		{
    			if(!rt||MxD(rt,P)<=Q.top()) return;LL t=D(V(rt),P);Q.top()<t&&(Q.pop(),Q.push(t),0);//与堆顶比较判断能否有贡献
    			RI d=MxD(S(rt,1),P)>=MxD(S(rt,0),P);Max(S(rt,d),P),Max(S(rt,d^1),P);//优先处理可能带来更优答案的子树
    		}
    	public:
    		I void Build(Point *P) {Build(1,n,rt,P);}
    		I void Max(Con Point& P) {Max(rt,P);}
    }K;
    int main()
    {
    	RI i;for(F.read(n),F.read(k),i=1;i<=2*k;++i) Q.push(0);//初始放入2k个0
    	for(i=1;i<=n;++i) F.read(p[i].x[0]),F.read(p[i].x[1]);K.Build(p);
    	for(i=1;i<=n;++i) K.Max(p[i]);return printf("%lld
    ",Q.top()),0;//枚举起点更新堆,输出答案
    }
    
  • 相关阅读:
    IOS开发--第三阶段--微博(8)(程序5)
    IOS开发--第三阶段--微博(7)(程序4)
    IOS开发--第三阶段--微博(6)(程序3)
    IOS开发--第三阶段--微博(5)(程序2)
    IOS开发--第三阶段--微博(4)(程序1)
    IOS开发--第三阶段--微博(3)(修改已创建应用的信息)
    ansible_模块和剧本ansible_bookplay
    自动化运维 ansible
    celery 基础
    sqlalchemy
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ4520.html
Copyright © 2011-2022 走看看