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;
}
posted @ 2023-06-20 11:59  jackle  阅读(2)  评论(0编辑  收藏  举报