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

来源:互联网 发布:mdict mac版 编辑:程序博客网 时间:2024/03/28 16:50

题目:

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