zoukankan      html  css  js  c++  java
  • 【题解】[SDOI2010]捉迷藏

    题目链接:https://www.luogu.com.cn/problem/P2479

    题目大意:求平面(n)个点中,到其它(n-1)个点的曼哈顿距离最大和最小距离之差最小的点,求出这个这个距离差。

    (K-D-Tree)维护区间,剪枝搜索。

    值得一提的是,对于(maxdis)的查询还是比较显然的,找到它到当前点所维护区间的端点的距离的最大值即可。对于最小距离……还是(对我来说)有点坑的。

    首先,判断最小距离的时候,当这个点在当前询问区间的话,它的距离显示为0,就炸了qwq,所以,求完这个距离,我们更新答案的时候应该判断是否是真的这个距离,即为零不更新。

    那么其它的都和(k)远点对差不多,没有重构,没有替罪羊

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    const int MAXN=5e5+10;
    #define inf 2147483647
    struct pt{
    	int x[2];
    }p[MAXN];
    int rt,D,tot,n,ans,ans1,ans2;
    int ls[MAXN],rs[MAXN];
    struct node{
    	int mi[2],mx[2],siz;
    	pt c;
    }tr[MAXN];
    inline void pushup(int x){
    	int l=ls[x],r=rs[x];
    	tr[x].siz=tr[l].siz+tr[r].siz+1;
    	for(int i=0;i<=1;++i){
    		tr[x].mi[i]=tr[x].mx[i]=tr[x].c.x[i];
    		if(l)tr[x].mi[i]=min(tr[x].mi[i],tr[l].mi[i]),tr[x].mx[i]=max(tr[x].mx[i],tr[l].mx[i]);
    		if(r)tr[x].mi[i]=min(tr[x].mi[i],tr[r].mi[i]),tr[x].mx[i]=max(tr[x].mx[i],tr[r].mx[i]);
    	}
    }
    int operator<(pt a,pt b){return a.x[D]<b.x[D];}
    int build(int l,int r,int d){
    	if(l>r)return 0;
    	int x=++tot,mid=l+r>>1;
    	D=d;nth_element(p+l,p+mid,p+r+1);
    	tr[x].c=p[mid];ls[x]=build(l,mid-1,d^1);
    	rs[x]=build(mid+1,r,d^1);pushup(x);return x;
    }
    inline int abs(int x){return x<0?-x:x;}
    inline int Get(pt x,pt y){return abs(x.x[0]-y.x[0])+abs(x.x[1]-y.x[1]);}
    int Getdis(int x,pt a){
    	int res=0;
    	for(int i=0;i<=1;++i){
    		res+=max(0,a.x[i]-tr[x].mx[i])+max(0,tr[x].mi[i]-a.x[i]);
    	}
    	return res;//min
    }
    int getdis(int x,pt a){
    	int res=0;
    	for(int i=0;i<=1;++i)res+=max(abs(tr[x].mi[i]-a.x[i]),abs(tr[x].mx[i]-a.x[i]));
    	return res;//max
    }
    void querymax(int x,pt y){
    	ans2=max(ans2,Get(tr[x].c,y));
    	int l=ls[x],r=rs[x],dl,dr;
    	dl=l?getdis(l,y):-inf;
    	dr=r?getdis(r,y):-inf;
    	if(dl>dr){
    		if(dl>ans2)querymax(l,y);
    		if(dr>ans2)querymax(r,y);
    	}
    	else{
    		if(dr>ans2)querymax(r,y);
    		if(dl>ans2)querymax(l,y);
    	}
    }
    void querymin(int x,pt y){
    	int tmp=Get(tr[x].c,y);
    	if(tmp)ans1=min(ans1,tmp);
    	int l=ls[x],r=rs[x],dl,dr;
    	dl=l?Getdis(l,y):inf;
    	dr=r?Getdis(r,y):inf;
    	if(dl<dr){
    		if(dl<ans1)querymin(l,y);
    		if(dr<ans1)querymin(r,y);
    	}
    	else{
    		if(dr<ans1)querymin(r,y);
    		if(dl<ans1)querymin(l,y);
    	}
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i)scanf("%d%d",&p[i].x[0],&p[i].x[1]);
    	rt=build(1,n,0);ans=inf;
    	for(int i=1;i<=n;++i){
    		ans1=inf,ans2=-inf;
    		querymax(rt,p[i]);
    		querymin(rt,p[i]);
    		ans=min(ans,ans2-ans1);
    		//cout<<"Casepoint"<<i<<":"<<ans<<" "<<ans2<<" "<<ans1<<endl;
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    Fedora 19安装Fcitx输入法并安装搜狗输入法资源包
    mac 功能修改。。。。
    Zend Studio / Ecliplse插件StartExplorer
    关于更改apache和mysql的路径的问题..
    解决fedora64下vim不能语法着色问题
    正则例一
    PHP中使用正则表达式详解 preg_match() preg_replace() preg_mat
    C语言正则表达式详解 regcomp() regexec() regfree()详解
    正则19-20
    正则表达式教程:30分钟让你精通正则表达式语法
  • 原文地址:https://www.cnblogs.com/h-lka/p/12003727.html
Copyright © 2011-2022 走看看