链接:https://ac.nowcoder.com/acm/problem/50937
来源:牛客网
来源:牛客网
题目描述
在一条数轴上有N家商店,它们的坐标分别为 A[1]~A[N]。现在需要在数轴上建立一家货仓,每天清晨,从货仓到每家商店都要运送一车商品。为了提高效率,求把货仓建在何处,可以使得货仓到每家商店的距离之和最小。
链接:https://ac.nowcoder.com/acm/problem/50937
来源:牛客网
来源:牛客网
备注:
对于100%的数据:N≤100000N\leq 100000N≤100000, A[i]≤1000000A[i]\leq 1000000A[i]≤1000000
本题可以使用前缀和和差分去解体,但不是单纯的使用前缀和和差分。
在这里面不是区域性的变化,所以第一眼看上去似乎不能使用前缀和和差分。但是可以创建一个map数组来保存保存在某个区间里面需要做什么样的连续变换(在某个区间里面彼此相加或者相见的数是一样的)。
比如:1:map[INT_MIN]--,map[1]+=2
2:map[INT_MIN]--,map[2]+=2
3:map[INT_MIN]--,map[3]+=2
4:map[INT_MIN]--,map[4]+=2
然后进行前缀和的累加,得到的结果就是在相邻区间里面彼此的差值。然后又有最大值或最小值一定在端点的位置(也就是1,2,6,9的位置)。所以计算出每一个端点的值就可以达到最小的总距离。
#include <iostream>
#include <cstdio>
#include <limits.h>
#include <map>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int MAXN = 1000002;
long long first_num = 0;
map<long long, long long> m = {};
long long res[MAXN];
int main() {
IOS;
int n, k;
cin>>n;
for (int i=1;i<=n;i++) {
cin>>k;
m[-INT_MAX]--;
m[k]+=2;
first_num+=k+(long long)INT_MAX;
}
//计算a的前缀和
map<long long, long long>::iterator it = m.begin();
int old = it->second;
for (++it;it!=m.end();it++) {
it->second = it->second+old;
old = it->second;
}
res[0] = first_num;
int min = INT_MAX;
//根据前缀和和first_num的值进行距离总和的计算
it = m.begin();
map<long long, long long>::iterator it2 = m.begin();
it2++;
int index = 1;
for (it;it2!=m.end();it++) {
res[index] = (it2->first-it->first)*(it->second)+res[index-1];
if (res[index]<min) {
min = res[index];
}
index++;
it2++;
}
cout<<min;
return 0;
}

京公网安备 11010502036488号