标签:lap div 变形 order where 技术 ace 不同 max
Input
Output
Sample Input
10 6 6 4 2 10 3 8 5 9 4 1
Sample Output
6500
题意:n块田地,每块田地有cows【i】头牛,求出一个长度不小于F的子段,使子段牛的平均数最大。
思路:我们令 avr = sum【i,j】/(i-j+1)
那么这题就是 求是avr的最大值,我们二分枚举ans,判断 avr 是否不小于 ans,即avr >= ans,为了不维护(i-j+1)的值,变形成sum【i,j】 - ans*(i-j+1) >= 0,
我们把原数组cows【i】-ans,那么Sum【i,j】 = sum【i,j】-ans(i-j+1)。
现在关键就是取得一个 max{Sum【i,j】},对于Sum【i,j】,我们可以用前缀和相减的方式求得,sum(i)-min(sum(j)), 0 <= j <= i-F。
坑点:注意最后答应的是二分的R值,我打印L值Wa的怀疑人生.而且题目要求精度是1e-4,当我们枚举的精度不小于题目要求精度的时候L和R值都是OK的
我感觉是如果两个值转换为整数不同的话,R值转换的整数值在L~R区间内的,而l转换的值是小于l的,如果两个值转换的值相同,打印那个都行,且整数肯定小于L。
其实像是最大值最小,最小值最大,都可以用二分解决,答案是单调的,这题还有种用凸包方法写的,以后再填坑吧。
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 5 const int maxn = 1e5+5; 6 int n,f; 7 int cows[maxn]; 8 const double eps = 1e-8; 9 10 bool solve(double x,int f) 11 { 12 double fcows[n+1]; 13 double sum[n+1]; 14 for(int i=1;i<=n;i++)fcows[i] = cows[i] - x; 15 for(int i=1;i<=n;i++)sum[i] = sum[i-1]+fcows[i]; 16 double ans = -1e10,minn = 1e10; 17 for(int i=f;i<=n;i++) 18 { 19 minn = min(minn,sum[i-f]); 20 ans = max(ans,sum[i]-minn); 21 } 22 return ans >= 0; 23 } 24 int main() 25 { 26 scanf("%d%d",&n,&f); 27 double low=0; 28 double high = 0; 29 for(int i=1;i<=n;i++) 30 { 31 scanf("%d",&cows[i]); 32 high += cows[i]; 33 } 34 while(low + eps < high) 35 { 36 double mid = (low+high)/2; 37 if(solve(mid,f))low = mid; 38 else high = mid; 39 } 40 printf("%d\n",(int)(1000*high)); 41 }
标签:lap div 变形 order where 技术 ace 不同 max
原文地址:https://www.cnblogs.com/iwannabe/p/10160942.html