Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 9985 | Accepted: 3237 |
Description
Input
Output
Sample Input
10 6 6 4 2 10 3 8 5 9 4 1
Sample Output
6500
这题可以用斜率优化做也可以用二分做,我用的是二分做法。
题意:给你n个牛的自身价值,让你找出连续的且数量大于等于F的一段区间,使这段区间内的牛的平均价值最大。
思路:用二分枚举平均值ave,每个牛的价值都减去ave,看是否有连续的超过f长度的区间使得这段区间的价值大于等于0,如果能找到,那么说明这个平均值可以达到。先每个a[i]减去ave得到b[i],用dp[i]表示以i为结尾区间连续长度大于等于f的最大连续区间和,maxx[i]表示以i为结尾的最大连续区间和,sum[i]表示1~i的价值总和那么maxx[i]=max(maxx[i-1]+b[i],b[i]),dp[i]=maxx[i-f+1]+sum[i]-sum[i-f+1],判断是否有一个i(i>=f)满足dp[i]>=0.
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<string> #include<algorithm> using namespace std; #define inf 99999999 #define maxn 100050 #define eps 1e-6 double sum[maxn],a[maxn],b[maxn],dp[maxn],maxx[maxn]; int main() { int n,m,i,j,f,ant; double l,r,mid,ans; while(scanf("%d%d",&n,&f)!=EOF) { l=2000.0;r=1.0; for(i=1;i<=n;i++){ scanf("%lf",&a[i]); l=min(l,a[i]); r=max(r,a[i]);//这里不能省,不然会影响精度 } while(r-l>eps){ mid=(l+r)/2.0; sum[0]=0;maxx[0]=0; for(i=1;i<=n;i++){ b[i]=a[i]-mid; sum[i]=sum[i-1]+b[i]; maxx[i]=max(b[i],maxx[i-1]+b[i]); } ans=sum[f]; for(i=f+1;i<=n;i++){ dp[i]=maxx[i-f+1]+sum[i]-sum[i-f+1]; if(ans<dp[i])ans=dp[i]; } if(ans>=0)l=mid; else r=mid; } ant=1000*r; printf("%d\n",ant); } return 0; }