• 【BZOJ1941】[SDOI2010] Hide and Seek(KD-Tree)


    点此看题面

    大致题意: 给定(n)个点,让你找到一个点,求出到这个点最远的距离和最近的距离之差的最小值。(距离为曼哈顿距离)

    前言

    一开始(WA)了一发,后来发现和闪指导一样(naive)了。。。

    然后又(TLE)了一发,本地测了一下似乎跑得还挺快的,后来发现是因为脑残没开(O2)。。。(话说为什么开个(O2)能快上(10)倍)

    不过总体上来看,没有修改只有询问的(KD-Tree)还真的挺好写的。

    大致思路

    这应该是比较简单的(KD-Tree)板子题。

    考虑枚举这个点,那么只要求出最远距离和最近距离即可。

    我们维护(KD-Tree)一个子树内横坐标最小值、最大值以及纵坐标最小值、最大值。

    每次若能取到的最优距离不可能对答案造成贡献就可以直接退出,且我们先处理可能带来更优答案的子树以提高效率。

    这里能取到的最远距离显然是横坐标之差绝对值的较大值加上纵坐标之差绝对值的较大值

    而所能取到的最近距离却不是横坐标之差绝对值的较小值加上纵坐标之差绝对值的较小值,因为如果这个点某一维在子树的矩阵范围之内,则这一维距离是可能为(0)的!这个地方要特别注意。

    其他似乎就没什么了,具体实现详见代码。

    代码

    #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
    using namespace std;
    int n,D;
    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,ans;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) (abs(A[0]-B[0])+abs(A[1]-B[1]))//两点距离
    		#define MxD(x,P) max(abs(P[0]-Mn(x)[0]),
    			abs(P[0]-Mx(x)[0]))+max(abs(P[1]-Mn(x)[1]),abs(P[1]-Mx(x)[1]))//最远距离
    		#define MnD(x,P) max(max(Mn(x)[0]-P[0],
    			P[0]-Mx(x)[0]),0)+max(max(Mn(x)[1]-P[1],P[1]-Mx(x)[1]),0)//最近距离
    		I void Max(CI rt,Con Point& P)//求最远距离
    		{
    			if(!rt||MxD(rt,P)<=ans) return;RI t=D(V(rt),P);ans<t&&(ans=t);//若不可能对答案造成贡献则退出
    			RI d=MxD(S(rt,1),P)>=MxD(S(rt,0),P);Max(S(rt,d),P),Max(S(rt,d^1),P);//优先处理可能带来更优答案的子树
    		}
    		I void Min(CI rt,Con Point& P)//求最近距离,和上面差不多
    		{
    			if(!rt||MnD(rt,P)>=ans) return;RI t=D(V(rt),P);t&&ans>t&&(ans=t);
    			RI d=MnD(S(rt,1),P)<=MnD(S(rt,0),P);Min(S(rt,d),P),Min(S(rt,d^1),P);
    		}
    	public:
    		I void Build(Point *P) {Build(1,n,rt,P);}
    		I int Max(Con Point& P) {return ans=0,Max(rt,P),ans;}
    		I int Min(Con Point& P) {return ans=1e9,Min(rt,P),ans;}
    }K;
    int main()
    {
    	RI i;for(F.read(n),i=1;i<=n;++i) F.read(p[i].x[0]),F.read(p[i].x[1]);K.Build(p);
    	RI t,ans=1e9;for(i=1;i<=n;++i) ans>(t=K.Max(p[i])-K.Min(p[i]))&&(ans=t);//枚举点计算答案
    	return printf("%d
    ",ans),0;
    }
    
  • 相关阅读:
    fastadmin+thinkphp,自定义编辑操作按钮修改数据
    fastadmin列表自动刷新功能
    【Linux】centos7安装nginx并配置web前端环境。
    一文精通HashMap灵魂七问,你学还是不学
    HttpServletRequest 的三个方法 request.getParameter()、request.getInputStream()、request.getReader()
    算法19可见的山峰对数量(单调栈)
    算法18最大值减去最小值小于或等于num的子数组数量
    自控力读书笔记20220704
    爬虫课程笔记02
    Python处理办公自动化的10大场景
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ1941.html
Copyright © 2020-2023  润新知