2020牛客暑期多校训练营(第八场) K

K.Kabaleo Lite

题目链接

题意:

有N个菜, 第 i 道菜有 盈利值 a[i] 和 数量 b[i]  , 每次给一位客人上菜 需要从第一道菜开始上,上完第一道菜才能上第二道菜 , 上完第二道菜才能上第三道菜 ...  以此类推

问 最多能给几个客人上菜 , 在客人最大化的情况下 ,最大盈利是多少(可能为负)

想法:

① 最多可以给b[1]个客人上菜 , 因为每个客人都一定要上第一道菜

② 假如 第 5 道菜数量为 1 , 第 6 道菜数量为 100 , 那么第 6 道菜的数量可以看做 1 ,因为 第 5 道菜只能上一次 , 而第 6 道菜只能在第 5 道上过了 才能上。

③ 计算一个 a[ i ] 前缀和 pre[ i ]  ,  含义是:总共上 [1  ~ i ]道菜 的利润

④ 只要从后往前 , 每次找到 [1 ~ i ] 中利润最高的 pre[ i ] ,然后看数量还够不够 , 如果够 , 就全取掉 , 如果不够 , 同理继续往前找。

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 10;
#define ll long long
#define int long long
template <typename T>
void read(T &res) {
    bool flag = false;
    char ch;
    while (!isdigit(ch = getchar())) (ch == '-') && (flag = true);
    for (res = ch - 48; isdigit(ch = getchar()); res = (res << 1) + (res << 3) + ch - 48)
        ;
    flag && (res = -res);
}
template <typename T>
void Out(T x) {
    if (x < 0)
        putchar('-'), x = -x;
    if (x > 9)
        Out(x / 10);
    putchar(x % 10 + '0');
}

int a[maxn] , b[maxn];
__int128 maxx[maxn] ,  pre[maxn];
signed main() {
    //ios;
    //cin.tie(0);
    int t;
    read(t);
    int num = 1;
    while(t --){
       int n;
       read(n);
       for(int i = 1 ; i <= n ; i ++) read(a[i]) , pre[i] = pre[i - 1] + a[i];
       for(int i = 1 ; i <= n ; i ++) read(b[i]);
       for(int i = 2 ; i <= n ; i ++) b[i] = min(b[i] , b[i - 1]);
       int pos = 1;
       maxx[1] = pos;
       for(int i = 2 ; i <= n ; i ++){
            if(pre[i] > pre[pos]){
                maxx[i] = i , pos = i;
            }
            else maxx[i] = maxx[i - 1];
       }
       __int128 ans = 0 , cnt = 0;
       for(__int128 i = n ; i >= 1 ; i --){
            __int128 now = maxx[i];
            if(cnt >= b[now])continue;
            ans += (b[now] - cnt) * pre[now];
            cnt += (b[now] - cnt);

       }
       cout << "Case #" << num ++ << ": " << b[1] << ' ';
       Out(ans);
       cout << '
';
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/GoodVv/p/13437260.html