题目链接:http://www.usaco.org/index.php?page=viewproblem2&cpid=419
题意:有1,000,000个整数,要求从第2个到n-1个之间,删去一段连续的数,使得剩余数的平均数最小。( 1<=所有数<= 1e6).
题解:二分法,二分一个平均密度p,使原序列均减去p,求得2~n-1的最大连续和,可得到剩余数的和的正负值。若为正,则p小于mid;否则,p大于mid。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<cmath> using namespace std; const int N = 1e5+10; const double eps = 1e-4; double a[N],b[N],high,low,sum; int n; double get(){ double ans = 0,sum=0; double fumax = -1e8; int fl=1; for(int i=2;i<=n-1;i++){ if(b[i]>0) fl=0; fumax = max(fumax,b[i]); } if(fl) return fumax; for(int i=2;i<=n-1;i++){ if(sum+b[i]>0) sum += b[i]; else sum = 0; ans = max(ans,sum); } return ans; } double solve(){ while(high-low>eps){ double mid = (low+high)/2; for(int i=1;i<=n;i++) b[i] = a[i]-mid; double maxd = get(); double tmp = sum-n*mid-maxd; if(tmp < 0) high = mid; else low = mid; } return low; } int main(){ // freopen("10.in","r",stdin); cin >> n; sum = 0; high = 1;low = 1e8; for(int i=1;i<=n;i++){ scanf("%lf",&a[i]); sum += a[i]; high = max(a[i],high); low = min(a[i],low); } double ans = solve(); printf("%.3lf\n",ans); return 0; }
时间: 2024-10-26 12:37:40