USACO Sabotage, 2014 Mar 破坏阴谋(二分+贪心)
一开始看完这题就有个想法:
只要把大于整个序列平均数的最大连续序列就是最优?
那把整个序列都减掉平均数 在做最大连续字序列和且记录长度?
仔细思考一下并不太对;
当子序列最大但长度较大 也许也比不上删去一个超过平均数许多的机器;
盲目的贪心是错的;但找对方向问题就解决了;
我们可以发现 若删除机器后平均值越小;超过这平均值的可删除的机器就越多;
满足了单调性 ;就可以二分了;
至于check()就是基于上面的贪心;也是预处理后做最大连续字序列和做判断;
T(nlogn)
#include<cstdio>
#include<cstring>
using namespace std;
double mid,a[100010],maxx,ans,s,l,r;
int n,i,j,k;
bool check(double x)
{
int num=0;double sum=0;
for(i=2;i<n;++i)
{
if(sum+a[i]>0)
sum+=a[i],num++;
else sum=a[i],num=1;
if(sum<a[i])sum=a[i],num=1;
if((ans-1.0*sum-num*x)/(n-num)<=mid)return true;
}
return false;
}
int main()
{
// freopen("xx.in","r",stdin);
scanf("%d",&n);
for(i=1;i<=n;++i)
{
scanf("%lf",&a[i]);
ans+=a[i];
}
r=1e9;l=1;
while(l+1e-6<r)
{
mid=(l+r)/2;
for(i=2;i<n;++i)a[i]-=mid;
if(check(mid))r=mid;
else l=mid;
for(i=2;i<n;++i)a[i]+=mid;
}
printf("%.3lf",r+5e-6);
}

浙公网安备 33010602011771号