noi.ac day1t1 candy

传送门

分析

我们知道如果设A,B分别为将两家店从大到小排序之后各自的前缀和,则

     Ans=Max{Min{A[i],B[j]}-W*(i+j)}。

为了得到这个Ans我们可以枚举两个数的Min,然后剩下那一个则使用二分求出在另一数列中大于Min的中最小的,这样的原因是为了使得W*(i+j)更小,从而在可能情况下达到最优。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
long long a[100100],b[100100];
int main(){
      long long n,m,i,j,k,w,Ans=0;
      scanf("%lld%lld",&n,&w);
      for(i=1;i<=n;i++)scanf("%lld",&a[i]);
      for(i=1;i<=n;i++)scanf("%lld",&b[i]);
      reverse(a+1,a+n+1);
      reverse(b+1,b+n+1);
      for(i=1;i<=n;i++)a[i]=a[i-1]+a[i];
      for(i=1;i<=n;i++)b[i]=b[i-1]+b[i];
      for(i=1;i<=n;i++){
          long long x=lower_bound(b+1,b+n+1,a[i])-b;
          if(x<=n)Ans=max(Ans,a[i]-w*(i+x));          
      }
      for(i=1;i<=n;i++){
          long long x=lower_bound(a+1,a+n+1,b[i])-a;
          if(x<=n)Ans=max(Ans,b[i]-w*(i+x));          
      }
      printf("%lld
",Ans);
      return 0;
}
原文地址:https://www.cnblogs.com/yzxverygood/p/9696888.html