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;
}


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