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


    题目链接

    【题目翻译】

    给你n个月,每个月天数有d[i]天

    你需要选取连续的几天(可以跨月、跨年)

    然后你得到的收益为这些天是在所在月份的第几天对应的数字的和。

    比如你选了第2月(设有30天)的第29、30天以及3月的第1,2天。

    那么你的收益就是29+30+1+2

    然后现在的问题是,让你从n个月份当中选出来连续的x天,要求他们的收益总和最大。

    【题解】

    首先需要明确一点,你选出来的这x天,最后一天肯定是某个月的最后一天。

    不然总能有更优的方案。

    证明如下:

    明白这一点之后就好做了。

    弄一个前i个月天数的前缀和pday[i]用来查前x天所在的月份。

    再弄一个前i个月(1+...+d[1]+1+...+d[2]+1+...+d[i])的每个月天数和的前缀和。用来查前x天的收益和。

    枚举最后一段在哪一个月,二分出来前x天所在月份,计算出相应代价就好。

    二分的时候注意边界,然后跨年的情况,你就直接把d[]再复制一遍到后面就行。

    【代码】

    #include<bits/stdc++.h>
    #define ll long long
    #define rei(x) scanf("%d",&x)
    #define rel(x) scanf("%I64d",&x)
    #define rep1(i,a,b) for (int i = a;i <= b;i++)
    #define rep2(i,a,b) for (int i = a;i >= b;i--)
    using namespace std;
    
    const int N = 4e5;
    
    int n;
    ll x,d[N+10],pday[N+10],ptot[N+10];
    
    int main(){
        //cout<<(1LL<<62)<<endl;
        #ifdef LOCAL_DEFINE
            freopen("D:\rush.txt","r",stdin);
        #endif
        int T;
        rei(n);rel(x);
        rep1(i,1,n) rel(d[i]);
        rep1(i,n+1,2*n) d[i] = d[i-n];
        n = n*2;
        rep1(i,1,n){
            //d[i]<=10^6
            //pday[i]<=2*10^12
    
            //4*10^5*10^12
            //4*10^17
            pday[i] = pday[i-1]+d[i];
            ptot[i] = ptot[i-1]+(1+d[i])*d[i]/2;
        }
        ll ans = 0;
        rep1(j,1,n){
            int l = 0,r = j,temp = j;
            //要找这样一个temp,p[j]-p[temp]<=x,p[j]-p[temp-1]>x
            while (l<=r){
                int mid = (l+r)/2;
                if ((pday[j]-pday[mid])<x){
                    temp = mid;
                    r = mid-1;
                }else l = mid + 1;
            }
            if (temp==0) continue;
            ll tmp = pday[j]-pday[temp];
            ll lastdays = x-tmp;
            ll totval = ptot[j]-ptot[temp];
            ll firstdays = d[temp]-lastdays;
            if (firstdays<0) continue;
            totval = (1+d[temp])*d[temp]/2 - (1+firstdays)*firstdays/2 + totval;
            ans = max(ans,totval);
        }
        printf("%lld
    ",ans);
        return 0;
    }
    
    
  • 相关阅读:
    关闭Axapta
    使用API操纵文件
    调用数据源里面的方法
    Axapta进度条应用
    过滤Form的数据源
    使用系统自动产生编号
    获取表中的所有字段
    打开浏览器URL
    报表的一些常用选项
    .NET中访问Oracle数据库链接:ORA02041: client database did not begin a transaction 问题的处理。
  • 原文地址:https://www.cnblogs.com/AWCXV/p/12978202.html
Copyright © 2020-2023  润新知