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\n",ans); } return 0; } /********************************************************************** Problem: 1947 User: CrimsonFantasy Language: C++ Result: AC Time:1124 ms Memory:1900 kb **********************************************************************/