Codeforces Round #645 (Div. 2) 重點:D:The Best Vacation

題目鏈接:點這裏

D. The Best Vacation

題意:一年有n個月,每個月有di天,給你len天假期,如果在每個月的第j天拜訪他人就會獲得j個擁抱,讓你最大化擁抱。
解題思路:主流思路叫做雙指針,但是不是雙指針的那種典型的寫法。首先做這道題之前需要證明一下,假期選擇天數的結尾一定是每個月的結尾天數。這是個非典型推論,我們來證明一下,首先上一下cf的證明在這裏插入圖片描述
首先使用的是反證法,首先設結尾爲x,結尾的右邊是x+1(因爲如果不是這樣的話,結尾就是月份的結尾)現在想使左移的值大於右移的值,那麼若成立,便可以一直左移,所以不是最優解;
既然知道了一定是在月末買,那我們可以輕鬆知道往前二分查找起點再把溢出的天數加一加,便可一切明瞭。
主要還是難在月末這個點 的貪心。

LL a[N];
int main(){
    int n ;
    LL len ;
    while(~scanf("%d %lld", &n , &len)){
        for(int i = 1; i <= n ; i ++){
            scanf("%lld" ,&a[i]);
            a[i+n] = a[i];
        }
        n *= 2;
        vector<LL> B={0},C={0};
        for(int i = 1; i <= n ;i ++){
            B.pb(B.back()+a[i]);
            C.pb(C.back()+a[i]*(a[i]+1)/2);
        }
        LL ans = 0;
        for(int i = 0 ; i < n ; i ++){
            if(B[i+1] >= len){
                int pos = upper_bound(B.begin(),B.end(),B[i+1]-len) - B.begin();
                LL cnt = C[i+1] - C[pos];
                LL day = B[i+1] - B[pos];
                LL more =  len - day;
                cnt += (a[pos]*(a[pos]+1)/2);
                cnt -= ((a[pos] - more)*(a[pos] - more + 1)/2);
                ans = max(ans, cnt);
            }
        }
        printf("%lld\n",ans);
    }
 
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章