codeforces 939E. Maximize!(二分答案)

本文介绍了一道Codeforces上的939E问题,该问题要求在单增数列中动态添加元素并查询子数列的最大值减平均值的最大值。作者指出,虽然有些解决方案使用三分法,但可以通过二分答案来解决。具体策略是找到加入最后一个数前的最大值和以最后一个数为最大值的值,然后构建新数组并证明其单调性,从而二分搜索最接近0的项。
摘要由CSDN通过智能技术生成

传送门
二分答案好题。
题意简述:要求支持动态在一个数列队尾加入一个新的数(保证数列单增),查询所有子数列的 最大值减平均值 的最大值。


然而网上一堆高人是用三分做的。
我们先考虑当前的答案有可能由什么构成。

  1. 加入最后一个数之前的最大值。
  2. 加入最后一个数之后,以最后一个数为最大值的值。

于是问题变成了去求 m i n { ( ∑ j = 1 i a i ) + a n i + 1 } min\{\frac{(\sum_{j=1}^ia_i)+a_n}{i+1}\} min{i+1(j=1iai)+an}
然后令 b i = ( ∑ j = 1 i a i ) + a n i + 1 , c i = b i − b i − 1 b_i=\frac{(\sum_{j=1}^ia_i)+a_n}{i+1},c_i=b_i-b_{i-1} bi=i+1(j=1iai)+anci=bibi1,可以用作差法证明 c c c数组单调,于是二分出 c c c最接近0的项就行了。
代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int N=5e5+5;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
typedef long long ll;
ll sum[N],a[N];
int tot=0;
double Ans=0;
inline void modify(){
	int l=1,r=tot-1,ans=1;
	while(l<=r){
		int mid=l+r>>1;
		ll fi=a[tot]-a[mid]*mid+sum[mid-1];
		if(fi<=0)r=mid-1;
		else l=mid+1,ans=mid;
	}
	Ans=max(Ans,a[tot]-1.0*(sum[ans]+a[tot])/(ans+1));
}
int main(){
	freopen("lx.in","r",stdin);
	for(ri op,tt=read();tt;--tt){
		op=read();
		if(op==1){
			a[++tot]=read(),sum[tot]=a[tot]+sum[tot-1];
			modify();
		}
		else printf("%.10lf\n",Ans);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值