• [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!

  • 相关阅读:
    bzoj4753: [Jsoi2016]最佳团体(分数规划+树形依赖背包)
    bzoj2956: 模积和(数论)
    51nod 1766 树上的最远点对(线段树)
    bzoj2621: [Usaco2012 Mar]Cows in a Skyscraper(状压DP)
    Codeforces Round #441 Div. 2题解
    bzoj4569: [Scoi2016]萌萌哒(ST表+并查集)
    iOS和Android后台机制对比
    UIApplicationDelegate 各方法回调时机
    iOS OC和JS的交互 javaScriptCore方法封装
    iOS应用的执行原理
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/10828868.html
Copyright © 2020-2023  润新知