CSDN食用链接:https://blog.csdn.net/qq_43906000/article/details/107774487
题目大意:给你n种菜,每种(b_i)盘,能够获得的利润为(a_i),每个人只能从1开始吃连续的种类的菜,问在满足人数最多的情况下的最大利润。
输入
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
。。。一开始读了假题,一直以为先满足利润最大。。。那么人数最多的话就只是(b_1)了。我们对盈利做个前缀和然后从大往下取就完事了。每次取的时候增加的人数就是当前的前缀最小值减去已经得到的人数。注意一下会爆long long,我们用一下__int128就好了。不过挺多编译器不太支持这玩意,DEV可以跑跑。
以下是AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mac=1e5+10;
const int inf=1e9+10;
struct node
{
int id;
ll dish;
bool operator<(const node&a)const{
return dish>a.dish;
}
}pt[mac];
__int128 ans=0;
ll sum[mac];
int mi[mac];
void _print(__int128 x)
{
if (x>=10) _print(x/10);
putchar(x%10+'0');
}
void print(__int128 x)
{
if (x<0) putchar('-'),x=-x;
_print(x);
}
int main(int argc, char const *argv[])
{
int t;
scanf ("%d",&t);
for (int cas=1; cas<=t; cas++){
int n,a1,b1;
scanf ("%d",&n);
for (int i=1; i<=n; i++){
int x;
scanf ("%d",&x);
if (i==1) a1=x;
sum[i]=sum[i-1]+x;
pt[i].dish=sum[i];
}
mi[0]=inf;
for (int i=1; i<=n; i++){
int x;
scanf ("%d",&x);
if (i==1) b1=x;
pt[i].id=i;
mi[i]=min(mi[i-1],x);
}
sort(pt+1,pt+1+n);
int pos=n+1,person=0;
ans=0;
for (int i=1; i<=n; i++){
if (pt[i].id>pos) continue;
if (mi[pt[i].id]<=person) continue;
ans+=(__int128)pt[i].dish*(mi[pt[i].id]-person);
person+=mi[pt[i].id]-person; pos=pt[i].id;
}
ans+=(__int128)(b1-person)*a1;
printf("Case #%d: %d ",cas,b1);
print(ans); printf("
");
}
return 0;
}