[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