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

D. The Best Vacation

You’ve been in love with Coronavirus-chan for a long time, but you didn’t know where she lived until now. And just now you found out that she lives in a faraway place called Naha.

You immediately decided to take a vacation and visit Coronavirus-chan. Your vacation lasts exactly x days and that’s the exact number of days you will spend visiting your friend. You will spend exactly x consecutive (successive) days visiting Coronavirus-chan.

They use a very unusual calendar in Naha: there are n months in a year, i-th month lasts exactly di days. Days in the i-th month are numbered from 1 to di. There are no leap years in Naha.

The mood of Coronavirus-chan (and, accordingly, her desire to hug you) depends on the number of the day in a month. In particular, you get j hugs if you visit Coronavirus-chan on the j-th day of the month.

You know about this feature of your friend and want to plan your trip to get as many hugs as possible (and then maybe you can win the heart of Coronavirus-chan).

Please note that your trip should not necessarily begin and end in the same year.

Input
The first line of input contains two integers n and x (1≤n≤2⋅105) — the number of months in the year and the number of days you can spend with your friend.

The second line contains n integers d1,d2,…,dn, di is the number of days in the i-th month (1≤di≤106).

It is guaranteed that 1≤x≤d1+d2+…+dn.

Output
Print one integer — the maximum number of hugs that you can get from Coronavirus-chan during the best vacation in your life.

原题目链接:https://codeforces.ml/contest/1358/problem/D

INPUT
3 2
1 3 1

OUTPUT
5
INPUT
3 6
3 3 3

OUTPUT
12
INPUT
5 6
4 2 3 1 3

OUTPUT
15

原题解

#include <iostream>
#include <algorithm>
#include <vector>

#define int long long

using namespace std;

signed main() {
  int n, len;
  cin >> n >> len;
  vector<int> A(2 * n);
  for (int i = 0; i < n; i++) {
    cin >> A[i];
    A[n + i] = A[i];
  }
  n *= 2;
  
  vector<int> B = {0}, C = {0};
  for (int i = 0; i < n; i++) 
    B.push_back(B.back() + A[i]);
  for (int i = 0; i < n; i++) 
    C.push_back(C.back() + (A[i] * (A[i] + 1)) / 2);
  int ans = 0;
  for (int i = 0; i < n; i++) {
    if (B[i + 1] >= len) {
      int z = upper_bound(B.begin(), B.end(), B[i + 1] - len) - B.begin();
      int cnt = C[i + 1] - C[z];
      int days = B[i + 1] - B[z];
      int too = len - days;
      cnt += ((A[z - 1] * (A[z - 1] + 1)) / 2);		//加上前一个月能得到的拥抱的数量
      cnt -= (((A[z - 1] - too) * (A[z - 1] - too + 1)) / 2);	//减去多余的前几天,只保留后面日期大的天数
      ans = max(ans, cnt);
    }
  }
  cout << ans;
}

A 数组保存输入的数据,即各个月的天数。

B 数组保存这个月之前的天数和,即 b[i] 为第1个月到第 i - 1个月的天数和。
如 b[3] = 第一个月的天数 + 第二个月的天数。

C 数组保存这个月之前的所能得到的拥抱的总数,即c[i] 为第1个月到第 i - 1个月所能得到的拥抱的数量。
比如输入的数据为第一组数据,那么 c[3] = 1+2+3+1+2+3 =12

a[i]*(a[i]+1)/2 表示当月的能得到的拥抱的数量

然后遍历整个B数组,找出比逗留天数 len 大的 b[i+1] , 然后用 upper_bound() 二分找出应该从哪个月开始,用 z 记录开始的时间, cnt 记录从第 z 个月到第 i 个月所能得到的拥抱的数量, days记录这段时间的天数和。

因为 upper_bound() 是二分找出比当前数大的第一个数,所以 days 可能会比所逗留的时间 len 短,因此要从前一个月中取后几天补上 , 而所要补上的天数,用 too 表示

重复以上过程,最终用 ans 保存最大的 cnt

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值