• Codeforces Round #645 (Div. 2) D、The Best Vacation


    题目链接:The Best Vacation

    题意:

    给你n个月份,每一个月份有di天。你可以呆在那里x天(x天要连续),如果你在某月的第y天呆在这。那么你的拥抱值就加y

    1<=n<=2e5

    1<=di<=1e6

    题解:

    首先这段日期的结尾一定是月末。下面证明

    如果x<=max(d1,d2...dn)

    那么肯定是在那个max(d1,d2...dn)那个月最后x天呆在那得到的拥抱值最大

    如果选取的这段日期至少覆盖到两个月份。如果右端点不是月末的话,假设左端点对应的日期大于右端点对应的日期,那么整体往左移动区间就能使得答案增加;同理假设左端点对应的日期小于右端点对应的日期可以整体往右移动。最后都会使得右端点靠到某个月的月末。

    代码:

    #include<stdio.h>
    #include<algorithm>
    #include<iostream>
    #include<string>
    #include<queue>
    #include<deque>
    #include<string.h>
    #include<map>
    #include <iostream>
    #include <math.h>
    #define Mem(a,b) memset(a,b,sizeof(a))
    const double II = acos(-1);
    const double PP = (II*1.0)/(180.00);
    using namespace std;
    typedef long long ll;
    const int INF=0x3f3f3f3f;
    const double eps=1e-6;
    const double PI=acos(-1);
    const int mod=998244353;
    const int maxn=2e5+10;
    long long d[400005];
    long long sum[400005];
    long long ssum[400005];
    long long ans=0;
    long long n,x;//xһ��Ҫ��long long ��Ϊ��d�ĺ�
    int check(long long mid,long long k)
    {
        if(sum[k]-sum[mid]>=x) return 0;
        else
        {
            if(sum[k]-sum[mid-1]>=x) return 1;
            else return 2;
        }
    }
    int main()
    {
        cin>>n>>x;
        int i;
        for(i=1;i<=n;i++)
        {
            scanf("%lld",&d[i]);
            d[i+n]=d[i];
        }
        for(i=1;i<=2*n;i++)
        {
            sum[i]=sum[i-1]+d[i];
            ssum[i]=ssum[i-1]+(1+d[i])*d[i]/2;
        }
        for(i=n+1;i<=2*n;i++)
        {
            long long l=1,r=i,mid,pos;
            while(1)
            {
                mid=(l+r)/2;
                int judge=check(mid,i);
                if(judge==2) r=mid;
                else if(judge==0) l=mid+1;
                else
                {
                    pos=mid;
                    break;
                }
            }
            if(pos==i)//��ͬһ����
            {
                ans=max(ans,x*d[i]-(long long)x*(x-1)/2*1);
            }
            else
            {
                long long temp=ssum[i]-ssum[pos];
                long long xx=x-(sum[i]-sum[pos]);
                temp+=xx*d[pos]-xx*(xx-1)/2;
                ans=max(ans,temp);
            }
    
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    MySQL索引原理及慢查询优化
    MySQL单表百万数据记录分页性能优化
    linux下crontab命令的使用
    php递归读取目录
    php实现函数重载
    php数组常见的几种遍历方法
    ArtTemplate 使用笔记
    打算换工作的伙伴们,快来看啦,各种职位,随便挑咯...
    看看国外的javascript题目,你能全部做对吗?(分享)
    逛园子,看到个练习题,小试了一把(淘宝ued的两道小题)
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/13361942.html
Copyright © 2020-2023  润新知