• luogu 2115 破坏(01分数规划)


    题意:给出一个序列,删除一个连续的子串后使得剩下的平均值最小。

    典型的01分数规划,令f(x)=(sum1[i]+sum2[j])/(i+j).sum1表示前缀和,sum2表示后缀和,那么我们就相当于求出f(x)的最小值。

    令f(x)=y,化简则有(sum1[i]-i*y)+(sum2[j]-j*y)=0,我们二分y,找出满足这个式子的y的最小值。

    根据这个式子可以把序列都减去一个y,这样就相当于求新序列的前缀和sum1[i]+sum2[j]>=0.

    实际上就是求min(sum1[i]+sum2[j])>=0,转化一下就变成了求新序列的最大子串和的经典DP问题。

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-7
    # define MOD 1024523
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=100005;
    //Code begin...
    
    int a[N], n;
    double b[N], dp[N], sum;
    
    bool check(double x){
       sum=0;
       FOR(i,1,n) b[i]=a[i]-x, sum+=b[i];
       double res=-INF;
       FO(i,2,n) {
           dp[i]=max(dp[i-1]+b[i],b[i]);
           res=max(res,dp[i]);
       }
       return sum<=res;
    }
    int main ()
    {
        scanf("%d",&n);
        FOR(i,1,n) scanf("%d",a+i);
        double l=0, r=INF, mid;
        FOR(i,1,200) {
            mid=(l+r)/2.0;
            if (check(mid)) r=mid;
            else l=mid;
        }
        printf("%.3lf
    ",mid);
        return 0;
    }
    View Code
  • 相关阅读:
    sqlserver2005分页
    windows计划任务
    sqlserver 2005 通信格式
    sqlserver 导出数据到excel
    所有连接sqlserver 2005 数据库的驱动程序
    Sql 2000 中行转列的查询方法
    [转] ASP.NET中使用javascript
    [转]17种常用正则表达式
    正则式正反向预编译(实战)
    正则表达式的正反向预编译
  • 原文地址:https://www.cnblogs.com/lishiyao/p/6836221.html
Copyright © 2020-2023  润新知