• [bzoj1096] [ZJOI2007]仓库建设


    有n个点,每个点有p和c和坐标x,现在每个点可以选择建一座仓库,花费c块软妹币,或者运到后面的仓库,花费坐标差*p块软妹币

    求最小花费 n<=1,000,000

    点j连到点i的花费是(si-sj)*pj=si*pj -sj*pj

    令gi=-si*pi

    如果j比k优秀,那么f[j]+g[j..i]+si*p[j..i]<f[k]+g[k..i]+si*p[k..i]

    (f[j]+g[j]-f[k]-g[k])/(p[j]-p[k])<s[i]

    斜率优化

    #include<iostream>
    #include<cstdio>
    #define ll long long
    #define MAXN 1000000
    #define INF 200000000
    #define eps 1e-8
    using namespace std;
    int read()
    {
        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;
    }
    int n,top=0,tail=1;+
    ll f[MAXN+5],p[MAXN+5],c[MAXN+5],s[MAXN+5],pp[MAXN+5],g[MAXN+5];
    int q[MAXN+5];
    
    double geth(int x,int y)
    {
        return (double)(g[x]-g[y])/(double)(p[x]-p[y]-eps);
    }
    
    int get(int i)
    {
        while(top-tail>=1&&geth(q[tail+1],q[tail])<s[i]) tail++;
        return q[tail];
    }
    
    void ins(int i)
    {
        while(top-tail>=1&&geth(q[top],q[top-1])>geth(i,q[top]))top--;
        q[++top]=i;
    }
    
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++)s[i]=read(),p[i]=read(),c[i]=read();
        for(int i=1;i<=n;i++)pp[i]=pp[i-1]-p[i]*s[i],p[i]+=p[i-1];
        for(int i=1;i<=n;i++)
        {
            int x=get(i);
            f[i]=f[x]+s[i]*(p[i-1]-p[x])+pp[i-1]-pp[x]+c[i];
            f[i]=min(f[i],s[i]*(p[i-1])+pp[i-1]+c[i]);
            g[i]=f[i]-pp[i];
            ins(i);
        }
        cout<<f[n];
        return 0;
    }
  • 相关阅读:
    4.12 IDEA 如何新建 Java 项目 (图文讲解, 良心教程)
    4.11 AndroidStudio快捷键总结
    4.9 Android AndroidX的迁移
    4.8 build.gradle中正确地导入RecyclerView依赖
    4.6 构建之法7
    4.5 构建之法6
    4.4 构建之法5
    4.3 构建之法4
    4.2 构建之法3
    4.1 构建之法2
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj1096.html
Copyright © 2020-2023  润新知