• 【bzoj3170】[Tjoi 2013]松鼠聚会 旋转坐标系


    题目描述

    有N个小松鼠,它们的家用一个点x,y表示,两个点的距离定义为:点(x,y)和它周围的8个点即上下左右四个点和对角的四个点,距离为1。现在N个松鼠要走到一个松鼠家去,求走过的最短距离。

    输入

    第一行给出数字N,表示有多少只小松鼠。0<=N<=10^5
    下面N行,每行给出x,y表示其家的坐标。
    -10^9<=x,y<=10^9

    输出

    表示为了聚会走的路程和最小为多少。

    样例输入

    6
    -4 -1
    -1 -2
    2 -4
    0 2
    0 3
    5 -2

    样例输出

    20


    题解

    旋转坐标系

    题目给出的切比雪夫距离不好求,我们可以旋转坐标系,将点$(x,y)$变为$(x+y,x-y)$,转化为曼哈顿距离。

    然后就可以对横纵坐标分开考虑,对于某一坐标我们要求的就是所有数与它差的绝对值之和。可以对所有数排序,然后二分查找,使用前缀和计算答案。

    最后别忘了把答案除2,因为旋转坐标系的过程中相当于把距离乘了2。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 100010
    using namespace std;
    typedef long long ll;
    ll x[N] , y[N] , tx[N] , ty[N] , sx[N] , sy[N];
    int main()
    {
    	int n , i , px , py;
    	ll ans = 1ll << 62 , vx , vy;
    	scanf("%d" , &n);
    	for(i = 1 ; i <= n ; i ++ ) scanf("%lld%lld" , &vx , &vy) , x[i] = tx[i] = vx + vy , y[i] = ty[i] = vx - vy;
    	sort(tx + 1 , tx + n + 1) , sort(ty + 1 , ty + n + 1);
    	for(i = 1 ; i <= n ; i ++ ) sx[i] = sx[i - 1] + tx[i] , sy[i] = sy[i - 1] + ty[i];
    	for(i = 1 ; i <= n ; i ++ )
    	{
    		px = lower_bound(tx + 1 , tx + n + 1 , x[i]) - tx , vx = (x[i] * px - sx[px]) + (sx[n] - sx[px] - x[i] * (n - px));
    		py = lower_bound(ty + 1 , ty + n + 1 , y[i]) - ty , vy = (y[i] * py - sy[py]) + (sy[n] - sy[py] - y[i] * (n - py));
    		ans = min(ans , vx + vy);
    	}
    	printf("%lld
    " , ans >> 1);
    	return 0;
    }
    

     

  • 相关阅读:
    USACO07FEB银牛派对
    求环总结
    NOIP2015信息传递(拓扑排序 / 并查集)
    APIO2012dispatching (左偏树)
    [编程题]山寨金闪闪 (面试题)
    【小米oj】简单直接全排列
    【小米oj】寻找归一数字
    【小米oj】dreamstart 的催促
    【小米oj】打羽毛球的小爱同学
    【小米oj】石头收藏家
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7391446.html
Copyright © 2020-2023  润新知