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

在这里插入图片描述
输入

2
3
2 -1 3
3 2 1
4
3 -2 3 -1
4 2 1 2

输出

Case #1: 3 8
Case #2: 4 13

说明

For test case 1, the maximum number of visitors is 3, one of a
possible solution is: The first visitor received food 1, the profit is
2. The second visitor received food 1, the profit is 2. The third visitor received food 1 + food 2 + food 3, the profit is 2 + (-1) + 3.

题意:
你有n种菜,每盘菜的价值分别为a[i],分别有b[i]盘,但是上菜的顺序必须从1-n,如果没有前菜那么后面的菜就不能上,求能招待最多的客人和最大利润。
题解:
这个数据范围有一点坑(1e91e91e5),long long 是开不下的然后就稍微开大一点,用__int128即可,但是他是没有输入输出的所以自定义一个read和print。

因为要吃前菜才能吃后面的菜,那么就存前缀和的的最大值放在stack里面,而且b[i]肯定>=b[i+1],更新过它们的值之后,求最大的利润即可
Code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#include<unordered_map>
#include<unordered_set>
#define ll long long
using namespace std;
const int INF=0x3f3f3f3f;
const double pi=acos(-1.0),eps=1e-8;
template <typename _Tp> inline void read(_Tp&x) {
    char ch;bool flag=0;x=0;
    while(ch=getchar(),!isdigit(ch)) if(ch=='-')flag=1;
    while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
    if(flag) x=-x;
}
inline void print(__int128 x) {
    if(x<0) {x=-x;putchar('-');}
    if(x>9) print(x/10);
    putchar(x%10+'0');
}
__int128 a[100005],b[100005];
int main()
{
    int T;
    scanf("%d",&T);
    int cas=1;
    while(T--)
    {
        int n;
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        stack<int>q;
        read(n);
        ll maxx=-INF;
        for(int i=1; i<=n; i++)
        {
            read(a[i]);
            a[i]+=a[i-1];
            if(maxx<a[i])
            {
                maxx=a[i];
                q.push(i);
            }
           // printf("%lld ",a[i]);
        }
        //printf("\n");
        //while(!q.empty())
        //{
        //    printf("%d ",q.front());
        //   q.pop();
        //}
        //printf("\n");

        for(int i=1; i<=n; i++)
        {
            read(b[i]);
            if(b[i]>b[i-1]&&i!=1)
            {
                b[i]=b[i-1];
            }
            // printf("%lld ",b[i]);
        }
        __int128 sum=0,num=0;
        int nn=b[1];
        while(!q.empty())
        {
            int xx=q.top();
            q.pop();
            //printf("%d ",xx);
            if(b[xx]<num)
                continue;
            b[xx]-=num;
            sum+=b[xx]*a[xx];
            num+=b[xx];
        }//printf("\n");
        printf("Case #%d: %d ",cas++,nn);
        print(sum);
        printf("\n");
    }
}
/*
200
3
2 -1 3
3 2 1
4
3 -2 3 -1
4 2 1 2
3
-1 -2 -1
4 3 2
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值