csu 1947 三分

题意:

长者对小明施加了膜法,使得小明每天起床就像马丁的早晨一样。 今天小明早上6点40醒来后发现自己变成了一名高中生,这时马上就要做早操了,小明连忙爬起来 他看到操场密密麻麻的人,突然灵光一闪想到了一个很严肃的问题: 操场上有n个人,第i个人的坐标为(xi, yi),刚开始每个人都站的很松散,现在想把所有人排成一行平行x轴紧挨着的队伍,求所有人需要移动的曼哈顿距离之和的最小值。

分析:

第一次三分高度,第二次,按照x 坐标排序,三分起点。

csuoj 不支持bits/stdc++.h %I64d

#include <cstdio>
#include <algorithm>

using namespace std;

const int maxn = 100000 + 5;

int n;
struct Point
{
    int x,y;
} node[maxn];

bool cmp(Point a,Point b)
{
    return a.x<b.x;
}


long long calc(int x)
{
    long long sum = 0;
    for(int i=0; i<n; i++)
        sum += abs(node[i].y-x);
    return sum;
}

long long calc2(int mid)
{
    long long ret=0;
    for(int i=0; i<n; i++)
        ret+=abs(node[i].x-mid-i);
    return ret;
}

int main()
{
    //freopen("in.txt","r",stdin);
    while(~scanf("%d",&n))
    {
        int L = 1e9,R = -1e9;
        for(int i=0; i<n; i++)
        {
            scanf("%d%d",&node[i].x,&node[i].y);
            L = min(L,node[i].y);
            R = max(R,node[i].y);
        }

        sort(node,node+n,cmp);

        while (L<R-1)
        {
            int lmid=(L+R)>>1;
            int rmid=(lmid+R)>>1;
            if (calc(lmid)<=calc(rmid)) R=rmid;
            else L=lmid;
        }

        long long ans=min(calc(L),calc(R));
        L=node[0].x-n-1;
        R=node[n-1].x;
        while (L<R-1)                    //三分起始点
        {
            int lmid=(L+R)>>1;
            int rmid=(lmid+R)>>1;
            if (calc2(lmid)<=calc2(rmid)) R=rmid;
            else L=lmid;
        }

        ans+=min(calc2(L),calc2(R));
        printf("%lld
",ans);
    }

    return 0;
}


/**********************************************************************
    Problem: 1947
    User: CrimsonFantasy
    Language: C++
    Result: AC
    Time:1124 ms
    Memory:1900 kb
**********************************************************************/
View Code
原文地址:https://www.cnblogs.com/TreeDream/p/7222607.html