首页 > 其他 > 详细

[USACO14MAR] 破坏Sabotage(二分答案,分数规划)

时间:2019-07-18 22:54:10      阅读:80      评论:0      收藏:0      [点我收藏+]

题目链接

Solution

去掉中间一段区间 \([l,r]\) 后剩下的平均值可以表示为 :
\[\frac{\sum^{n}_{i=1}{v_i}-\sum^{r}_{i=l}{v_i}}{n-(r-l+1)}\]
二分的答案如果要满足条件,即:
\[\frac{\sum^{n}_{i=1}{v_i}-\sum^{r}_{i=l}{v_i}}{n-(r-l+1)}<Ans\]
移一下项,然后可以得到:
\[{\sum^{n}_{i=1}{(v_i-Ans)}<\sum^{r}_{i=l}{(v_i-Ans)}}\]
然后这两个式子的意义就是全局 \(v_i-Ans\) 的和比中间这段 \(v_i-Ans\) 要小.
所以只需要有一段前缀和与一段后缀和之和小于等于 \(0\) ,那么答案即满足条件。

Code

#include<bits/stdc++.h>
#define db double
#define ll long long
#define inf 0x3f3f3f3f3f3f3f
#define N 100008
using namespace std;
const db opt=0.00001;

void in(ll &x)
{
    char ch=getchar();ll f=1,w=0;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){w=w*10+ch-'0';ch=getchar();}
    x=f*w; return;
}

db a[N];ll n;

bool judge(db st)
{
    db sum[N],dum[N],sm[N],dm[N];
    sum[0]=dum[N+1]=0; 
      sm[0]=dm[n+1]=inf;
    for(int i=1;i<=n;i++)
       sum[i]=sum[i-1]+a[i]-st,
          sm[i]=min(sm[i-1],sum[i]);
    for(int i=n;i>=1;i--)
       dum[i]=dum[i+1]+a[i]-st,
          dm[i]=min(dm[i+1],dum[i]);
    for(int i=2;i<n;i++)
       if(sm[i-1]+dm[i+1]<=0)return 1;
    return 0;       
}

int main()
{
    db ans=inf,l=inf,r=0;
    in(n);
    for(int i=1;i<=n;i++)
    {
        ll x; in(x);
        a[i]=x*1.0;
        l=min(a[i],l);
        r=max(a[i],r);
    }   
    while(l<=r)
    {
        db mid=(l+r)/2;
        if(judge(mid))ans=min(ans,mid),r=mid-opt;
        else l=mid+opt;
    }
    if(ans==inf)printf("%.3lf\n",(a[1]+a[n])/(2*1.0));
    else printf("%.3lf\n",ans);
    return 0;
}

[USACO14MAR] 破坏Sabotage(二分答案,分数规划)

原文:https://www.cnblogs.com/Kv-Stalin/p/11209746.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!