Codeforces Round #645 (Div. 2)D.The Best Vacation(贪心)

思路:
考虑某个区间,对于这个区间左右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;
}

猜你喜欢

转载自blog.csdn.net/weixin_43571920/article/details/106393442