https://codeforces.com/contest/1358/problem/D
题目
某地一年有$n$个月,第$i$个月有$d_i$天,每个月的第$j$天可以被拥抱$j$次,你需要选择连续的x天,问你最多能被拥抱多少次,$x<sum d_i$
$1 leqslant n leqslant 2 cdot 10^5$,$1 leqslant d_i leqslant 10^6$
题解
非常难受的一道题,最后10分钟才证出来,CF上的证明是反证……
如果把前i天的被抱次数列出来,得到$a_i$
[1,quad2,quad3,cdots,quad d_1,1quad 2, cdots, d_n]
然后考虑前n项和$S_n$,问题是求最大的$S_n-S_{n-x}$
变形一下
[sum_n (a_n-a_{n-x})]
然后画一个图

发现极大值只可能在一个月的最后一天取得
最后枚举最后一天,然后计算就可以了
还要注意x会爆int
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 400007
int d[MAXN];//, b[MAXN];
long long s[MAXN], ss[MAXN];
int n;
long long x;
long long calc(long long i) {
int ii=lower_bound(s+1,s+n+n+1,i)-s-1;
long long ri=i-s[ii];
return ss[ii]+(ri+1ll)*ri/2;
}
int main() {
scanf("%d%lld", &n, &x);
d[0]=0;
for(int i=1; i<=n; i++) scanf("%d", &d[i]);
for(int i=1; i<=n; i++) d[i+n]=d[i];
s[0]=0; ss[0]=0;
for(int i=1; i<=n+n; i++) s[i]=s[i-1]+d[i];
for(int i=1; i<=n+n; i++) ss[i]=ss[i-1]+(d[i]+1ll)*d[i]/2;
long long ans=-1;
for(int i=1; i<=n; i++) {
ans = max(ans, calc(s[i+n])-calc(s[i+n]-x));
}
printf("%lld
", ans);
}