zoukankan      html  css  js  c++  java
  • [bzoj1941][sdoi2010]Hide and Seek

    传送门

    Description

    平面上(n)个点,一个点的贡献是离他最远的点的距离减去离他最近的点的距离,求最小的贡献

    距离是曼哈顿距离

    (nleq 500000)

    Solution 

    k-d tree 模板题

    建树过程相当于每次按照一维把超平面上的点进行划分,(O(nlog n))

    用到函数

    std::nth_element(a+l,a+mid,a+r+1);
    

    可以取得排序后的中位数

    k-d tree 常用来解决平面最近点问题

    最坏复杂度为(O(sqrt n)),平均复杂度是(O(log n))

    对于查找一个节点的最近点

    从根开始,假设当前递归到一个节点,先用这个点更新答案。

    然后对于它的两个孩子,优先选择离当前点近的一个矩形,递归更新答案

    然后更新完答案如果到另一个儿子的那个矩形距离比答案小就也用另一个儿子递归更新答案。

    一个节点到矩形的距离指的是到矩形边界的最远距离,显然这个值不一定能取到


    Code 

    #include<bits/stdc++.h>
    #define ll long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)>(b)?(b):(a))
    #define abs(x) ((x)>0?(x):-(x))
    #define reg register
    inline int read()
    {
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x*f;
    }
    
    const int MN=5e5+5,inf=0x3f3f3f3f;
    int n,mn,mx,now;
    struct Point{
    	int d[2],mx[2],mn[2],l,r;
        int& operator[](int x){return d[x];}
        bool operator<(const Point&x)const{return d[now]<x.d[now];}
        friend int dis(Point x,Point y){return abs(x.d[0]-y.d[0])+abs(x.d[1]-y.d[1]);}
    }a[MN];
    
    struct KDtree{
    	Point p[MN],T;
    	void up(int x)
    	{
    		int l=p[x].l,r=p[x].r;
    		for(reg int i=0;i<2;++i)
    		{
    			if(l) p[x].mn[i]=min(p[x].mn[i],p[l].mn[i]),
                      p[x].mx[i]=max(p[x].mx[i],p[l].mx[i]);
                if(r) p[x].mn[i]=min(p[x].mn[i],p[r].mn[i]),
                      p[x].mx[i]=max(p[x].mx[i],p[r].mx[i]);
    		}
    	}
        int getmn(Point x)
        {
            reg int r=0;
            for(reg int i=0;i<2;++i)
                r+=max(x.mn[i]-T[i],0),r+=max(T[i]-x.mx[i],0); 
            return r;
        }
        int getmx(Point x)
        {
            reg int r=0;
            for(reg int i=0;i<2;++i)
                r+=max(abs(x.mn[i]-T[i]),abs(x.mx[i]-T[i]));
            return r;
        }
        int build(int l,int r,int th)
        {
        	if(l>r) return 0;
            reg int mid=(l+r)>>1;now=th;
            std::nth_element(a+l,a+mid,a+r+1);p[mid]=a[mid];
            for(reg int i=0;i<2;++i) p[mid].mx[i]=p[mid].mn[i]=a[mid][i];
            p[mid].l=build(l,mid-1,th^1);p[mid].r=build(mid+1,r,th^1);up(mid);
            return mid;
        }
        void qmn(int k)
        {
            int t=dis(p[k],T);if(t)mn=min(mn,t);
            int dl=inf,dr=inf;
            if(p[k].l) dl=getmn(p[p[k].l]);
            if(p[k].r) dr=getmn(p[p[k].r]);    
            if(dl>dr){if(dr<mn) qmn(p[k].r);if(dl<mn)qmn(p[k].l);}
            else{if(dl<mn)qmn(p[k].l);if(dr<mn)qmn(p[k].r);}
        }
        void qmx(int k)
        {
            mx=max(mx,dis(p[k],T));
            int dl=-inf,dr=-inf;
            if(p[k].l) dl=getmx(p[p[k].l]);
            if(p[k].r) dr=getmx(p[p[k].r]);
            if(dl>dr){if(dl>mx) qmx(p[k].l);if(dr>mx)qmx(p[k].r);} 
            else{if(dr>mx) qmx(p[k].r);if(dl>mx)qmx(p[k].l);}
        } 
    }kdtree;
    int rt,ans;
    
    int main()
    {
    	n=read();
    	reg int i;
    	for(i=1;i<=n;++i) a[i][0]=read(),a[i][1]=read();
    	rt=kdtree.build(1,n,0);
    	for(ans=inf,i=1;i<=n;++i)
    	{
    		kdtree.T=a[i];
    		mn=inf;kdtree.qmn(rt);
    		mx=-inf;kdtree.qmx(rt);
    		ans=min(ans,mx-mn);
    	}
    	return 0*printf("%d
    ",ans);
    }
    


    Blog来自PaperCloud,未经允许,请勿转载,TKS!

  • 相关阅读:
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    关于http
    事件循环机制
    关于常问的输入URL到看到页面发生的全过程
    浅拷贝
    基础知识链接
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/10828868.html
Copyright © 2011-2022 走看看