Codeforces Round #645 (Div. 2)D. The Best Vacation
假设:一年有n个月,第i个月有d[i]天,每个月是从1号开始到d[i]号,即1,2,3…d[i]号。设某月的某天是s号,就可以获得s个hug拥抱。
输入一个x,你需要从这中选出连续的x天,使得其获得的hug拥抱数量最大。
需要注意是的这连续的x天中可以有下一年的天数,也就是说这里可以构成一个环,故可以预处理第二年的月份天数,即d[i+n]=d[i]。
题解:
最有解的最后一天肯定某月份的月底。
前缀和预处理每个月份的天数,
找出连续的x天,
利用二分找出满足连续x的的月份,还需要考虑最开始的一个月只取了一部分。
再前缀和数组减出区间和,贪心比较每次的获得hug拥抱数量即可。
#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define ll long long
#define _for(i,a,b) for(int i = (a);i<(b);i++)
#define endl '\n'
#define inf 0x3f3f3f3f
using namespace std;
const int mod=1e9+7;
const int MAX=1e6+7;
ll a[MAX],sum_day[MAX],sum_hug[MAX];
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
ll n,x;cin>>n>>x;
for(int i=1;i<=n;i++)
{
cin>>a[i];
a[i+n]=a[i];
}
for(int i=1;i<=2*n;i++)
{
sum_day[i]+=a[i]+sum_day[i-1];
sum_hug[i]+=a[i]*(a[i]+1)/2+sum_hug[i-1];
}
ll ans=0;
for(int i=1;i<=2*n;i++)
{
if(sum_day[i]>=x)
{
int p=lower_bound(sum_day+1,sum_day+2*n+1,sum_day[i]-x)-sum_day;
ll res=sum_day[p]-(sum_day[i]-x);
ll last=(a[p]+a[p]-res+1)*res/2;
ans=max(ans,last+sum_hug[i]-sum_hug[p]);
}
}
cout<<ans<<endl;
}