• 解题:APIO 2014 序列分割


    题面

    拆开式子我们发现切割顺序不影响答案,所以可以设计出一个$dp[i][j]$表示到$i$为止切了$j$刀的最大收益之类的,然后做个前缀和就可以转移了。

    $dp[i][j]=min(dp[i][j],dp[k][j-1]+sum[k]*(sum[i]-sum[k]) )$

    第一维显然还可以滚掉,这样就有了一个$O(n^2k)$的做法 因为跑不满如果再卡卡常大概可以得到50pts的成绩

    开始优化,假如现在在$i$而先不管切了几刀,有两个位置$j$和$k$满足$j<k$且$j$比$k$优,那么有

    $dp[j]+sum[j]*(sum[i]-sum[j])<dp[k]+sum[k]*(sum[i]-sum[k])$

    $dp[j]-sum[j]^2-(dp[k]-sum[k]^2)<(sum[k]-sum[j])*sum[i]$

    $frac{dp[j]-sum[j]^2-(dp[k]-sum[k]^2)}{(sum[k]-sum[j])}<sum[i]$

    — —斜率优化,而sum[i]又是单增的,所以每次直接取队头就完事了

    注意:因为是非负序列,可能会出现斜率不存在的情况,记得判掉

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=100005,K=205;
     6 int n,k,f,b,p,tra[K][N],que[N];
     7 long long sum[N],dp1[N],dp2[N];
     8 double Slope(int a,int b)
     9 {
    10     if(sum[a]==sum[b]) return -1e9;
    11     return 1.0*(sum[b]*sum[b]-dp1[b]-(sum[a]*sum[a]-dp1[a]))/(sum[b]-sum[a]);
    12 }
    13 int main()
    14 {
    15     scanf("%d%d",&n,&k);
    16     for(int i=1;i<=n;i++)
    17         scanf("%lld",&sum[i]),sum[i]+=sum[i-1];
    18     for(int i=1;i<=k;i++)
    19     {
    20         f=0,b=-1;
    21         for(int j=1;j<=n;j++)
    22         {
    23             while(f<b&&Slope(que[f],que[f+1])<=sum[j]) f++;
    24             p=que[f],dp2[j]=dp1[p]+(sum[j]-sum[p])*sum[p],tra[i][j]=p;
    25             while(f<b&&Slope(que[b-1],que[b])>=Slope(que[b],j)) b--;
    26             que[++b]=j;
    27         }
    28         swap(dp1,dp2);
    29     }
    30     printf("%lld
    ",dp1[n]),p=tra[k--][n];
    31     while(p) printf("%d ",p),p=tra[k--][p];
    32     return 0;
    33 }
    View Code
  • 相关阅读:
    vue+axios实现文件下载
    处理 Vue 单页面应用 SEO
    JSON.parse()与JSON.stringify()的区别
    JS设置Cookie过期时间
    <div>标签仿<textarea>。contentEditable=‘true’,赋予非表单标签内容可以编辑
    CSS上下左右居中的几种方法
    jqGrid 修改单元格值或者替换图片及其他
    对于Web性能优化, 了解和经验
    初步了解反射案列
    JS IndexOf移除符合规则的一项
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/10222171.html
Copyright © 2020-2023  润新知