hdu 4311 - Meeting point-1(预处理)

题目:

Meeting point-1

题意:给一群点,求所有点到某一点的距离之和的最小值,距离 = |x1-x2| + |y1-y2|


思路:直接枚举肯定超时。第一次做的时候是假定一维中位数定理在二维也成立,即:最小位置在中心的那群点(x,y接近中位数),然后x,y同时操作后超时了,于是改为仅对x排序,枚举中间n/2 - 300 , n/2 + 300的点,水过了。。。。。之后补题,用了预处理的方式,具体见代码注释


代码:

//#pragma comment(linker, "/STACK:102400000,102400000")
#include "iostream"
#include "cstring"
#include "algorithm"
#include "cmath"
#include "cstdio"
#include "sstream"
#include "queue"
#include "vector"
#include "string"
#include "stack"
#include "cstdlib"
#include "deque"
#include "fstream"
#include "map"
using namespace std;
typedef long long LL;
const long long INF = (long long)1e30;
const int MAXN = 100000+100;
#define eps 1e-14
const int mod = 100000007;

int n;

struct node
{
    LL x,y;
    LL id;
} p[MAXN];                          //标号从1开始

LL sumx[MAXN],sumy[MAXN];           //sumx[i]表示从1到i的点的横座标之和,sumy[i]同理,为纵座标之和

LL minll(LL a , LL b)
{
    if(a < b)
        return a;
    return b;
}

bool cmp1(node a, node b)
{
    if(a.x == b.x)
        return a.y < b.y;
    return a.x < b.x;
}

bool cmp2(node a, node b)
{
    if(a.y == b.y)
        return a.x < b.x;
    return a.y < b.y;
}

int main()
{
    //freopen("in","r",stdin);
    //freopen("out","w",stdout);

    int t;
    scanf("%d",&t);

    while(t--)
    {
        scanf("%d" , &n);
        memset(sumx , 0 , sizeof(sumx));
        memset(sumy , 0 , sizeof(sumy));

        for(int i = 1 ; i <= n ; i++)
            scanf("%I64d %I64d" , &p[i].x , &p[i].y);

        sort(p+1,p+n+1,cmp1);                   //首先对x排序,预处理sumx,这样sumx[i]-sumx[j]表示从j+1~i的点的横座标之和
                                                //sumx[i]-sumx[j] - p[j].x*(i-j)就表示i~j之间的点到j点的距离

        sumx[1] = p[1].x;
        for(int i = 2 ; i <= n ; i++)
            sumx[i] = sumx[i-1] + p[i].x;

        sort(p+1,p+n+1,cmp2);                   //对y排序,并同样方法预处理sumy,由于之后我们还得按x排回来,所以此时记录一下某点在y
                                                //方式排列时的位置:id

        sumy[1] = p[1].y;
        p[1].id = 1;
        for(int i = 2 ; i <= n ; i++)
        {
            sumy[i] = sumy[i-1] + p[i].y;
            p[i].id=i;
        }

        sort(p+1,p+n+1,cmp1);

        LL minc = INF;

        for(int i = 1 ; i <= n ; i++)
        {
            LL pre = (i)*p[i].x - sumx[i]                           //前i个点到i点的距离之和
                        + (sumx[n] - sumx[i] - (n-i)*p[i].x);       //后n-i个点到i点的距离之和
            LL pos = p[i].id;                                       //导出i点在y排列时的位置pos

            pre += ((pos)*p[i].y-sumy[pos])                         //同样的计算方法
                        + (sumy[n] - sumy[pos] - (n-pos)*p[i].y);
            minc = minll(minc , pre);
        }

        printf("%I64d\n",minc);

    }

    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章