Noi.ac#30 题解

题目链接

\(Solution:\)

看着题目的约束条件,可以看出是一道二分答案的题目(话说暴力有\(90pts?\))
我们考虑\(a,b\)的单调性,我们所取的糖果必然是\(a\)\(b\)的后缀和(不过为什么我用了前缀和来实现)
所以我们分别枚举\(a,b\)的后缀,对另一个数组二分出愉悦度大于当前枚举数组的最小值,取\(max\)即可

\(Code:\)

#include<bits/stdc++.h>
using namespace std;
namespace my_std
{
    typedef long long ll;
    #define fr(i,x,y) for(ll i=(x);i<=(y);i++)
    inline ll read()
    {
        ll sum=0,f=1;
        char ch=0;
        while(!isdigit(ch))
        {
            if(ch=='-') f=-1;
            ch=getchar();
        }
        while(isdigit(ch))
        {
            sum=(sum<<1)+(sum<<3)+(ch^48);
            ch=getchar();
        }
        return sum*f;
    }
    inline void write(ll x)
    {
        if(x<0)
        {
            putchar('-');
            x=-x;
        }
        if(x>9) write(x/10);
        putchar(x%10+'0');
    }
}
using namespace my_std;
const ll N=1e5+50;
ll n,w,a[N],b[N],s1[N],s2[N],ans1,ans2;
inline bool ck1(int pos,int sum){return s2[n]-s2[n-pos]>=sum;}
inline bool ck2(int pos,int sum){return s1[n]-s1[n-pos]>=sum;} 
int main(void)
{
    n=read(),w=read();
    fr(i,1,n) a[i]=read();
    fr(i,1,n) b[i]=read();
//  reverse(a+1,a+n+1);
//  reverse(b+1,b+n+1);
    fr(i,1,n) s1[i]=s1[i-1]+a[i];
    fr(i,1,n) s2[i]=s2[i-1]+b[i];
    fr(i,1,n)
    {
        ll sum=s1[n]-s1[n-i],l=1,r=n;
        while(l<=r)
        {
            ll mid=(l+r)>>1;
            if(ck1(mid,sum))
            {
                ans1=max(ans1,sum-(i+mid)*w);
                r=mid-1;
            }
            else l=mid+1;
        }
    }
    fr(i,1,n)
    {
        ll sum=s2[n]-s2[n-i],l=1,r=n;
        while(l<=r)
        {
            ll mid=(l+r)>>1;
            if(ck2(mid,sum))
            {
                ans2=max(ans2,sum-(i+mid)*w);
                r=mid-1;
            }
            else l=mid+1;
        }
    }
    write(max(ans1,ans2));
    putchar('\n');
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lgj-lgj/p/12334750.html