zoukankan      html  css  js  c++  java
  • P2115 [USACO14MAR]破坏(二分答案)

    给定一串数,问删除中间一段,剩下的平均数最小是多少;

    不容易想到这是个二分。

    $solution:$

    来手玩一点式子:

    首先很容易想到一个前缀和$sum_i $表示i到1的前缀和,这样就能很容易地O(1)查询区间和/差

    二分一个mid,作为最小的平均数。

    假设删去区间为l~r(lr都删)

    平均数等于:

    $ave={sum_{i-1} + sum_{n-j} }/{n-(j-i+1)}$

    于是,这里就就有了单调性:

    $mid leq ave$

    稍微变形一下,就得到

    $sum_n-sum_j+sum_{i-1} leq mid*n-mid*j+mid*(i-1)$

    $(sum_n-mid*n) geq (sum_j-mid*j) - (sum_{i-1}-mid*(i-1)  $

    令$sum_i-i*mid$=$C_i$

    则只需要判断

    $C_n geq C_j - C_{i-1} $

    就能判断二分边界了。

    复杂度$O(n)$

    稍微注意下边界,就能A掉了。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+233;
    double sum[maxn];
    int n;
    double c[maxn];
    double maxx[maxn];
    double minn[maxn];
    bool check(double x)
    {
        for(int i=0;i<=n;i++)
        {
            c[i]=sum[i]-i*x;
        }
        minn[1]=c[1];
        for(int i=2;i<=n;i++)
        {
            minn[i]=min(c[i],minn[i-1]);
        }
        maxx[n-1]=c[n-1];
        for(int i=n-2;i>=1;i--)
        {
            maxx[i]=max(c[i],maxx[i+1]);
        }
        for(int i=2;i<n;i++)
        {
            if(maxx[i]-minn[i-1]>c[n])
            return 1;
        }
        return 0;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            double x;
            scanf("%lf",&x);
            sum[i]=sum[i-1]+x;
        }
        double l=0,r=1e4+233;
        while((r-l)>0.000000001)
        {
            double mid=(l+r)/2;
            if(check(mid)==0)
            l=mid;
            else
            r=mid;
        }
        printf("%.3lf",l);
        return 0;
    }

    (完)

     

  • 相关阅读:
    汇编笔记
    C++知识点复习
    flask 初步
    flask and postgre on heroku
    google zxing二维码库 初始
    flasklogin解读
    flasksqlalchemy 关系(一对多)
    flask的信号
    flask 范例学习
    github 操作纪录
  • 原文地址:https://www.cnblogs.com/ajmddzp/p/11772904.html
Copyright © 2011-2022 走看看