P2115 [USACO14MAR]破坏Sabotage

题意:给你一个正整数序列,让你删去一段区间内的数[l,r] $1<l\le r <n$

   使得剩余的数平均值最小$n\le 10^5$

1、不难想到暴力,用前缀和优化$O(n^2)$

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<cmath>
using namespace std;
#define int long long
#define olinr return
#define _ 0
#define love_nmr 0
#define DB double
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')
            f=-f;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
inline void put(int x)
{
    if(x<0)
    {
        x=-x;
        putchar('-');
    }
    if(x>9)
        put(x/10);
    putchar(x%10+'0');
}
double ans=0x7fffffff;
int a[105050];
int s[105050];
int n;
signed main()
{
    n=read();
    for(int i=1;i<=n;i++)
    {
        a[i]=read();
        s[i]=s[i-1]+a[i];
    }
    for(int i=2;i<n;i++)
        for(int j=i;j<n;j++)
        {
            int tot=s[n]-(s[j]-s[i-1]);
            ans=min(ans,(double)(tot)/(double)(n-(j-i+1)));
        }
    printf("%.3lf",ans);
    olinr ~~(0^_^0)+love_nmr;
}
暴力

2、正解:二分答案!

    怎么二分呢(我没看出来

    于是深(da)入(kai)思(ti)考(jie)

    发现对于暴力,可以变个形

    $\frac{sum[n]-(sum[j]-sum[i])}{n-(j-i)}\ge x(二分一个答案x)$

    $sum[n]-sum[j]+sum[i]\ge nx-jx+ix$

    $(sum[n]-nx)+(sum[i]-ix)-(sum[j]-jx)\ge 0$

    卧槽,好神奇

    那么,我们令$a=sum[a]-ia$

    直接O(n)看看答案是否成立,

    因此总复杂度$O(nlogn)$

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<cmath>
using namespace std;
#define int long long
#define olinr return
#define _ 0
#define love_nmr 0
#define DB double
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')
            f=-f;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
inline void put(int x)
{
    if(x<0)
    {
        x=-x;
        putchar('-');
    }
    if(x>9)
        put(x/10);
    putchar(x%10+'0');
}
int s[105050];
int n;
double a[105050];
double minn;
double eps=1e-4;
inline bool ok(double mid)
{
    for(int i=1;i<=n;i++)
        a[i]=(double)s[i]-i*mid;
    minn=a[1];
    for(int i=2;i<n;i++)
    {
        if(a[n]-(a[i]-minn)<=0) return false;
        minn=min(minn,a[i]);
    }
    return true;
}
signed main()
{
    n=read();
    for(int i=1;i<=n;i++)
        s[i]=s[i-1]+read();
    double l=0;
    double r=(double)(s[n]-(s[n-1]-s[1]))/(double)(2.0);
    while(r-l>=eps)
    {
        double mid=(double)(l+r)/(double)2.0;
        if(ok(mid))
            l=mid;
        else
            r=mid;
    }
    printf("%.3lf",l);
    olinr ~~(0^_^0)+love_nmr;
}

    

    

猜你喜欢

转载自www.cnblogs.com/olinr/p/9578289.html
今日推荐