题目描述
给定一个长度为 n n n的非负整数序列 A A A,求一个平均数最大的,长度不小于 L L L的子段。
【输入形式】
第 1 行用空格分隔的两个整数 n n n和 L L L ;
第 2 行到第 n + 1 n+1 n+1行每行一个数字,分别为 n n n个非负整数,表示 A i A_i Ai 。
【输出形式】
输出一个整数,表示这个平均数的 1000倍。不用四舍五入,直接输出。
【样例输入】
10 6
6
4
2
10
3
8
5
9
4
1
【样例输出】
6500
【样例说明】
选 10 3 8 5 9 4
【数据范围】
1 < = n < = 1 0 5 1<=n<=10^5 1<=n<=105, 0 < = A i < = 2000 0<=A_i<=2000 0<=Ai<=2000
解题思路
二分查找+最大前缀和
代码
public class Main {
public static int binarySearch(int n,int L,double a[]) {
double b[]=new double[n+1];
double pre[]=new double[n+1];
double low=-2e3,high=2e3;
while(high-low>1e-10) {
double mid=(high+low)/2;
for(int i=1;i<=n;i++) {
b[i]= a[i]-mid;
pre[i]=pre[i-1]+b[i];
}
double max=-2e8,min=2e8;
for(int i=L;i<=n;i++) { //从L开始枚举右端点
min=Math.min(min, pre[i-L]);//最小的前缀
max=Math.max(max, pre[i]-min);//前缀和(大于L)减去最小的前缀 ,得到连续(大于L)的最大和
}
if(max>=0) {
low=mid;
}else {
high=mid;
}
}
return (int)(high*1000);
}
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int n=in.nextInt();
int L=in.nextInt();
double a[]=new double[n+1];
for(int i=0;i<n;i++) {
a[i]=in.nextDouble();
}
System.out.print(binarySearch(n,L,a));
}
}