思路:
考虑某个区间,对于这个区间左右2端点,如果左端点的值大于右端点值,那么我们把整个窗口往左移肯定会使答案增加,反之如果左端点的值小于右端点值,那么我们把整个窗口往右移肯定会使答案增加,知道左右端点相等,这样可以得到,我们结束的点一定是在某个月月末,然后我们就枚举每个月,处理一下前缀,用二分找一下。
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 4e5+10;
#define IOS ios::sync_with_stdio(0)
#define ull unsigned ll
#define uint unsigned
#define pai pair<int,int>
#define pal pair<ll,ll>
#define IT iterator
#define pb push_back
#define fi first
#define se second
#define For(i,j,k) for (int i=(int)(j);i<=(int)(k);++i)
#define Rep(i,j,k) for (int i=(int)(j);i>=(int)(k);--i)
#define endl '\n'
#define ll long long
const ll mod = 1e9+7;
ll a[man],sum[man],pre[man];
int main() {
#ifndef ONLINE_JUDGE
//freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
int n;
ll x;
cin >> n >> x;
for(int i = 2*n; i > n;--i){
cin >> a[i];
a[i-n] = a[i];
}
for(int i = 1;i <= 2*n;++i){
sum[i] = sum[i-1] + a[i];
pre[i] = pre[i-1] + (a[i] + 1)*a[i]/2;
}
ll ans = -1;
for(int i = 1;i <= n;i++){
ll tp = x + sum[i-1];
int id = upper_bound(sum+1,sum+1+2*n,tp) - sum;
id--;
ll s = x - sum[id] + sum[i-1];
//printf("s:%lld ",s);
s = (a[id+1] - s + 1 + a[id+1]) * s / 2;
//printf("s:%lld \n",s);
ans = max(ans,s+pre[id]-pre[i-1]);
}
cout << ans << endl;
return 0;
}