codeforces 645 div2——D

题目

很明显我们要令到拥抱数最大,我们尽可能让假期在月尾开始且在月尾结束,天数不够我们尽可能让假期在月尾结束(代码好写),这个贪心是正确的是因为我们让假期在月尾结束,往前x天,也能保证假期尽量晚的开始,所以能保证取到的天数最大。所以大体思路是枚举我们在哪一个月结束,二分找我们要从哪里开始休假,然后取最大值就好了,具体实现看代码。

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<stack>
#include<utility>
#define int long long
using namespace std;
int n,x;
int d[500000],sum1[500000],sum2[500000],ans=-1; 
signed main()
{
	cin>>n>>x;
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&d[i]);
		d[i+n]=d[i];
	}
	int n2=n*2;
	for(int i=1;i<=n2;i++)//这是个前缀和,方便处理数据
	{
		sum1[i]=sum1[i-1]+d[i];//这是月份天数的前缀和
		sum2[i]=sum2[i-1]+((1+d[i])*d[i]/2);//这个是可以获取到的拥抱的前缀和
	}
	for(int i=n+1;i<=n2;i++)//找开始的月份
	{
		int l=1,r=i;
		while(l<r)
		{
			int mid=l+r>>1;
			if(sum1[i]-sum1[mid]<x)
			{
				r=mid;
			}
			else
			{
				l=mid+1;
			}
		}
		int k=sum1[i]-sum1[l-1]-x;
		ans=max(ans,sum2[i]-sum2[l-1]-((1+k)*k/2));//如果x天不足以支撑用完一个月份,我们就把开始天数减掉,这个可以保证我们尽量晚的开始
	}
	cout<<ans;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章