题目来源:https://ac.nowcoder.com/acm/contest/5673/K
题意:有n道菜,第i道菜的利润为ai,且有bi盘。你要按照下列要求给顾客上菜。
每位顾客至少有一道菜
给顾客上菜时,都必须从第一道菜开始,上连续的编号的菜,例如,你可能给一位顾客 上的菜为第一道,第二道,第三道,但是不能为只上第二道而不上第一道,或者第一道,第三道中间缺少第二道。
求这些菜能够容纳的最大顾客数,并且求出在容纳最多顾客时的利润最大为多少。

解题思路:首先要求最大利润,可以采用贪心策略,在满足条件时,优先选取利润最大的,由于是 1~i的连续的菜,可以先求出前i份菜的利润的前缀和。然后按利润前缀和大小排序,从大到小遍历,对于前n份菜利润为sum的贡献,计算方法可以求出前n种菜剩余的菜的最小的数量min,让答案累加min∗sum,然后将前n种菜的数量都减去min。

关键词:前缀和,贪心算法

/*前缀和*/ 
#include<bits/stdc++.h>
using namespace std;
const long long N=1e5+9,mod=1e14;
long long a[N],b[N],s[N],n,m,ans;
int main()
{
    int q,t,l,r,i,j,k;
    cin>>q;
    while(q--)
    {
        memset(a,0,sizeof(a)),memset(b,0,sizeof(b)),memset(s,0,sizeof(s));//置空处理。 
        cin>>n;
        for(i=0;i<n;i++)
        cin>>a[i];
        cin>>b[0];
        for(i=1;i<n;i++) 
        {
            cin>>b[i];
            b[i]=min(b[i],b[i-1]);      
        }
        s[0]=a[0];
        for(i=1;i<n;i++) 
        s[i]=s[i-1]+a[i];        //前缀和处理 
        l=r=t=ans=0;
        m=s[l]*b[l];
        while(r<n)
        {
            while(r<n&&s[r]<=s[l]) 
            r++;
            if(r==n)break;
            m+=b[r]*(s[r]-s[l]);
            ans+=m/mod,m%=mod;
            l=r,t=0;
        }
        cout<<k<<b[0]<<endl;
        if(ans) 
        cout<<ans<<m;
        else
        cout<<m<<endl;
    }
    return 0; 
}