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); }