Codeforces Round #645 (Div. 2)D. The Best Vacation 前缀和+二分

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;
	 
 	
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章