返回顶部

Codeforces Round #645 (Div. 2) D. The Best Vacation (贪心,二分)

  • 题意:一年有\(n\)个月,每月有\(d_{i}\)天,找出连续的\(x\)天,使得这\(x\)天的日期总和最大,任意一年都能选.

  • 题解:首先要先贪心,得到:连续的\(x\)天的最后一天一定是某个月的最后一天,我们先预处理两个前缀和,分别记录连续的天数和总日期数,然后枚举,二分找出一个区间,得出这个区间的总日期数再加上区间最左边的剩余的\(x\)的总日期,每次维护一个最大值即可.(记得开\(long\ long\))

  • 代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <stack>
    #include <queue>
    #include <vector>
    #include <map>
    #include <set>
    #include <unordered_set>
    #include <unordered_map>
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    #define me memset
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    typedef pair<int,int> PII;
    typedef pair<ll,ll> PLL;
    
    ll n,x;
    ll a[N];
    ll pre1[N],pre2[N];
    int main() {
        ios::sync_with_stdio(false);cin.tie(0);
        cin>>n>>x;
        for(int i=1;i<=n;++i){
            cin>>a[i];
            a[n+i]=a[i];
        }
        n*=2;
        for(int i=1;i<=n;++i){
            pre1[i]=pre1[i-1]+a[i];
            pre2[i]=pre2[i-1]+a[i]*(a[i]+1)/2;
        }
        ll ans=0;
        for(int i=1;i<=n;++i){
            if(pre1[i]>=x){
               int pos=lower_bound(pre1+1,pre1+1+n,pre1[i]-x)-pre1;
               ll rest=x-(pre1[i]-pre1[pos]);
               ll res=(pre2[i]-pre2[pos])+(a[pos]+a[pos]-rest+1)*rest/2;
               ans=max(ans,res);
            }
        }
        printf("%lld\n",ans);
    
        return 0;
    }
    
posted @ 2020-05-27 14:23  _Kolibri  阅读(212)  评论(0)    收藏  举报