很明顯我們要令到擁抱數最大,我們儘可能讓假期在月尾開始且在月尾結束,天數不夠我們儘可能讓假期在月尾結束(代碼好寫),這個貪心是正確的是因爲我們讓假期在月尾結束,往前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;
}