zoukankan      html  css  js  c++  java
  • [斜率优化][DP]luogu P3648 序列分割

    https://www.luogu.org/problemnew/show/P3648

    分析

    首先我们先证明,分割的顺序与答案无关

    设有三段a,b,c

    a(b+c)+bc=ab+ac+bc①

    ab+(a+b)c=ab+ac+bc②

    ①=②

    假装证明了

    然后我们设f[i][k]表示第i个数字的后面分割,共分割了k次的最大分数

    f[i][k]=min(f[j][k-1]+s[j]*(s[i]-s[j])) (j<i) s为前缀和

    这个比较显然的斜率优化柿子

    单调队列维护一个下凸壳即可

    #include <iostream>
    #include <cstdio>
    #include <memory.h>
    using namespace std;
    typedef long long ll;
    const int N=1e5+10;
    int h,t,q[N];
    ll f[N][2],s[N],from[310][N];
    int n,k;
    
    double XL(int i,int j,int k) {
        if (s[k]-s[j]==0) return -2147483647;
        return 1.0*(f[j][(i+1)&1]-s[j]*s[j]-f[k][(i+1)&1]+s[k]*s[k])/(s[k]-s[j]);
    }
    
    int main() {
        scanf("%d%d",&n,&k);
        for (int i=1;i<=n;i++) scanf("%lld",&s[i]),s[i]+=s[i-1];
        for (int j=k-1;j>=0;j--) {
            q[h=t=1]=0;
            for (int i=1;i<=n;i++) {
                while (h<t&&XL(j,q[h],q[h+1])<=s[i]) h++;
                f[i][j&1]=f[q[h]][(j+1)&1]+s[q[h]]*(s[i]-s[q[h]]);
                from[j][i]=q[h];
                while (h<t&&XL(j,q[t-1],q[t])>=XL(j,q[t],i)) t--;
                q[++t]=i;
            }
        }
        int x=n,j=0;
        printf("%lld
    ",f[n][0]);
        while (j<k) {
            x=from[j][x];
            printf("%d ",x);
            j++;
        }
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    month(字段)、year(字段)
    简单音乐播放器实现
    Mp3音乐文件列表实现
    读取SD卡中所有MP3文件
    java基础复习 之 多态
    JavaWeb学习过程 之c3p0的使用
    JavaWeb学习过程 之MVC模式下的查询
    行转列:总结
    如何快速禁用约束 (解决ORA-O2266问题)
    PLSQL Developer 11 使用技巧(持续更新)
  • 原文地址:https://www.cnblogs.com/mastervan/p/11141464.html
Copyright © 2011-2022 走看看