2023-6-20
A. Vasya and Robot
题意:
给你一个序列 \(q\),你需要消除这个序列,每次你可以选择消除目前序列的第一个元素或者最后一个元素,你消除第一个元素的代价将是 \(l*q[i]\) ,消除最后一个元素的代价是 \(r*q[i]\) 。同时如果你当前取走的方式和上一次是一样的,你将会付出额外的代价,若这次和上次都是取第一个,你将会额外付出 \(ql\) 代价,同理若这一次和上一次都是取最后一个,你将会额外付出 \(qr\) 代价,现在问你把整个序列消除的最小代价是多少?
数据范围:
\(1\leq n \leq 10^5; 1\leq l,r\leq 100;1\leq ql,qr\leq 10^4\)
\(Tutorial:\)
这种前后取序列的问题,我们通常都会想到枚举,我们可以枚举前面 \(i\) 个元素是用第一种方法取,那么自然后面的 \(n-i\) 个元素都是用第二种方法取,那么我们可以很轻易的得到价值:
- 若 \(n-i>i\),即右边的元素更多,那么我们可以利用前后交错方法的去取,最后剩下 \(n-2*i-1\) 个元素是需要付出额外的 \(qr\) 代价
- 若 \(i>n-i\),即左边的元素更多,那么我们可以利用前后交错方法的去取,最后剩下 \(2*i-n-1\) 个元素是需要付出额外的 \(ql\) 代价
- 若 \(n-i=i\),两边元素一样多,故我们一定可以利用前后交错把整个序列取了,不用付出任何额外代价
故我们可以得到代价就是:
- 若 \(i>n-i\),\(res=l*pre+r*(sum-pre)+ql*(2*i-n-1)\)
- 若 \(n-i>i\),\(res=l*pre+r*(sum-pre)+qr*(n-2*i-1)\)
- 若 \(n-i=i\),\(res=l*pre+r*(sum-pre)\)
枚举所有情况,然后取最小值即可
\(Code:\)
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
int q[N];
int main () {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, l, r, ql, qr;
cin >> n >> l >> r >> ql >> qr;
int sum = 0;
for (int i = 1; i <= n; i++) {
cin >> q[i];
sum += q[i];
}
LL ans = 1e18;
int pre = 0;
for (int i = 0; i <= n; i++) {
LL res = 0;
pre += q[i];
res += l * pre + r * (sum - pre);
if (n - i > i) {
res += qr * (n - 2 * i - 1);
}
if (i > n - i) {
res += ql * (2 * i - n - 1);
}
ans = min(ans, res);
}
cout << ans << '\n';
return 0;
}