输入
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
*/