题目就不在这里记录了,蓝桥杯官网都有,以后想看可以回去找找。
前缀和
本题的主要思想就是利用前缀和,记录对应位置前面所有石头要移动到此处的费用和后面所有石头要移动到此处的费用,对每一个位置进行这样的记录,并对此比较大小。
细节
1、将数组中盛放pair容器,使用方便快捷。
2、起初检测的时候总是所有点都不通过,但是题目给的样例却可以通过。原因是题目样例数据很小,而题目给出的重量w和距离p的大小范围都是1~1e5,所以费用最后算起来绝对会大于1e10,也就大于了int的最大范围2^31-1(一个int是4Byte,也就是32bit),所以要用long long长整型。
#include <bits/stdc++.h>
using namespace std;
using ll = long long; //注意数据大小
using s = pair<int, int>;
const int maxn = 1e5 + 9;
s arr[maxn];
ll pre[maxn], nex[maxn]; //记录前面所有的石头移到此位置的费用,和后面所有石头移到此位置的费用
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n; cin >> n;
for (int i = 1; i <= n; i++) {
int w, p; cin >> w >> p;
arr[i].first = p;
arr[i].second = w;
}
sort(arr + 1, arr + n + 1);
ll tw = 0;
for (int i = 1; i <= n; i++) {
pre[i] = pre[i - 1] + tw * (arr[i].first - arr[i - 1].first);
tw += arr[i].second;
}
tw = 0; //目前石头总重量
for (int i = n; i >= 1; i--) {
nex[i] = nex[i + 1] + tw * (arr[i + 1].first - arr[i].first);
tw += arr[i].second;
}
ll ans = pre[1] + nex[1];
for (int i = 1; i <= n; i++) {
ans = min(ans, pre[i] + nex[i]);
}
cout << ans << endl;
return 0;
}
ps:一开始真没想到要用前缀和写,但这个思路确实是最好的,希望对前缀和可以越来越熟悉!