zoukankan      html  css  js  c++  java
  • 牛客第二场-双二分+枚举左右端点+前缀和

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const ll maxn = 500007;
    ll n;
    ll t;
    ll x[maxn],a[maxn];
    ll sum_num[maxn];
    ll sum_t[maxn];
    void init()
    {
        sum_num[0]=0;
        sum_t[0]=0;
        for (int i=1; i<=n; i++)
        {
            scanf("%lld",&x[i]);
        }
        for (int i=1; i<=n; i++)
        {
            scanf("%lld",&a[i]);
            sum_num[i] = sum_num[i-1]+a[i];//前i项物品总和
            sum_t[i] = sum_t[i-1]+2*a[i]*x[i];//物品运送到0需要花费的体力
        }
    }
    ll le(ll l,ll r)
    {
        return (sum_t[r]-sum_t[l-1])-(sum_num[r]-sum_num[l-1])*x[l]*2;//看成先移到0,再移到l
    }
    ll rr(ll l,ll r)
    {
        return (sum_num[r]-sum_num[l-1])*x[r]*2-(sum_t[r]-sum_t[l-1]);//看成先移到0,再移到r,由于必为正值所以取相反数
    }
    bool jug(ll ans){
       ll l,r,mid,mid_num;
       mid_num=ans/2+1;
       l=r=mid=1;
       while(1){//枚举右端点
        while(r<=n && (sum_num[r]-sum_num[l-1]<ans))r++;//枚举一个合理的r
        while(mid<r && (sum_num[mid]-sum_num[l-1])<mid_num)mid++;//再枚举这个合理mid
        if(r>n || mid>n)break;
        ll tmp = (sum_num[r]-sum_num[l-1])-ans;
        if (rr(l,mid)+le(mid,r)-2*tmp*(x[r]-x[mid])<=t)//满足情况
            return 1;
        l++;//后左边更新
       }
       l=r=mid=n;
       while(1)//先枚举右端点
       {
           while(l>=1 && (sum_num[r]-sum_num[l-1])<ans)l--;//枚举合理的l
           while(mid>l && (sum_num[r]-sum_num[mid-1]<mid_num))mid--;
           if (l<1 || mid<l)break;
           ll tmp =(sum_num[r]-sum_num[l-1])-ans;
           if (rr(l,mid)+le(mid,r)-2*tmp*(x[mid]-x[l])<t)
            return 1;
           r--;
       }
       return 0;
    }
    void solve()
    {
        ll l,r,mid,res;
        l=1;
        r=sum_num[n];
        while(l<=r)//二分答案
        {
            mid=(l+r)/2;
            if (jug(mid))//验证是否是更优秀的
            {
                res=mid;
                l=mid+1;
            }
            else
            {
                r=mid-1;
            }
        }
        printf("%lld
    ",res);
    }
    int main()
    {
        while(~scanf("%lld%lld",&n,&t))
        {
            init();
           solve();
        }
        return 0;
    }
    有不懂欢迎咨询 QQ:1326487164(添加时记得备注)
  • 相关阅读:
    C语言第十一周作业
    C语言第十周作业
    C语言第九周编程作业
    C语言第八周编程作业
    C语言第七周作业
    第六周作业
    第五周作业
    第四周作业
    第三周作业
    【BZOJ1488】[HNOI2009]图的同构计数
  • 原文地址:https://www.cnblogs.com/bluefly-hrbust/p/9594075.html
Copyright © 2011-2022 走看看