[BZOJ 2017.11月 月赛] 组题

题目传送-BZOJ5090

题意:

给出n个数。求连续区间(长度大于等于k)最大平均值。
\(n \le 100000\)

题解:

二分答案,用double
O(n)check:先把原数组都减去二分的答案,判断有没有一段长度大于等于K的区间的元素和大于等于0就行了

过程:

由于BZOJ评测机过慢。。二分最大二分次数T了不知道多少发。。

代码:

inline db sgn(db x) {return x<-eps ? -1 : x>eps;}
const int N=100010;
int a[N];
db b[N];
int n,k;
int l,r;
inline bool judge(db x) {
	for(int i=1;i<=n;i++) b[i]=1.0*a[i]-x;
	db sum=0,pre=0,mi=0; l=1; r=k;
	for(int i=1;i<=k;i++) sum+=b[i]; if(sgn(sum)>=0) return true;
	for(int i=k+1;i<=n;i++) {
		sum+=b[i]; sum-=b[i-k];
	// if(x==1.25) printf("%lf\n",sum);
		pre+=b[i-k];
		if(pre<mi) {mi=pre; l=i-k+1;}
		if(sum+pre-mi>=0) {r=i; return true;}
	}
	return false;
}
signed main()
{
	read(n); read(k);
	for(int i=1;i<=n;i++) read(a[i]);
	db L=-1e8,R=1e8;
	db ret=0;
	int T=100;
	while(T--) {
		// printf("%lf %lf\n",L,R);
		db mid=(L+R)*0.5;
		if(judge(mid)) {ret=mid; L=mid;}
		else R=mid;
	}
	// assert(judge(1.25));
	assert(judge(ret));
	ll fz=0,fm=0;
	for(int i=l;i<=r;i++) fz+=a[i];
	fm=r-l+1;
	bool fl=0;
	if(fz<0) fl=1,fz=-fz;
	ll g=__gcd(fz,fm);
	// printf("%lld %lld %d %d\n",fz,fm,l,r);
	if(fl) putchar('-');
	printf("%lld/%lld\n",fz/g,fm/g);
	
	return 0;
}

用时:1h

posted @ 2018-08-08 13:46  functionendless  阅读(140)  评论(0编辑  收藏  举报