zoukankan      html  css  js  c++  java
  • [USACO14MAR]破坏Sabotage

    还是二分答案,发现我的$check$函数不太一样,来水一发题解

    列一下式子

    $$frac{sum-sum[l,r]}{n-(r-l+1)}<=ans$$

    乘过去

    $$sum-sum[l,r]<=ans*(n-r+l-1)$$



    $$sum_{i=1}^{l-1}+sum_{i=r+1}^{n}<=ans*(n-r+l-1)$$

    $$sum{(a_i-ans)}<=0$$

    所以我们在$check$函数中,可以处理出$a_i-ans$数组

    然后求个前缀和,后缀和,前缀最小值,后缀最小值,对于每个位置考虑这个位置的前缀最小和这个位置之后(因为不能一个不删)的后缀最小是否非负即可

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int maxn=1e5+10;
    const double eps=1e-6;
    int n,m[maxn];
    double ans,sum1[maxn],sum2[maxn],mn1[maxn],mn2[maxn],a[maxn];
    bool check(double x)
    {
        for(int i=0;i<=n+1;i++)
            mn1[i]=mn2[i]=1e9;
        for(int i=1;i<=n;i++)
            a[i]=m[i]-x;
        for(int i=1;i<=n;i++)
            sum1[i]=sum1[i-1]+a[i],mn1[i]=min(sum1[i],mn1[i-1]);
        for(int i=n;i;i--)
            sum2[i]=sum2[i+1]+a[i],mn2[i]=min(sum2[i],mn2[i+1]);
        for(int i=1;i<n-1;i++)
            if(mn1[i]+mn2[i+2]<=0)
                return 1;
        return 0;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&m[i]);
        double l=1,r=10000;
        while(r-l>eps)
        {
            double mid=(l+r)/2;
            if(check(mid))
                r=mid-eps,ans=mid;
            else
                l=mid+eps;
        }
        printf("%.3lf
    ",ans);
        return 0;
    }
  • 相关阅读:
    关于平衡树的一些总结
    bzoj3065 带插入区间K小值
    bzoj2560 串珠子
    bzoj3224 Tyvj 1728 普通平衡树
    bzoj1031 [JSOI2007]字符加密Cipher
    bzoj4571 [Scoi2016]美味
    集合框架—常见的Set集合
    集合框架—两种迭代机制
    集合框架—基础
    网络编程—代码—UDP数据报传输
  • 原文地址:https://www.cnblogs.com/ivanovcraft/p/9783843.html
Copyright © 2011-2022 走看看