zoukankan      html  css  js  c++  java
  • HDU 3507 PrintArticle (单调队列优化)

    题意:给出一个数列C,一个数字M,将数列分成若干段,每段的代价为(设这段的数字为k个):

    dp[i]=min(dp[j]+(sum[i]-sum[j])*(sum[i]-sum[j])+M)

    若j1<j2且j2比j1优

    dp[j1]+sum[i]^2+sum[j1]^2-2*sum[i]*sum[j1]+M>dp[j2]+sum[i]^2+sum[j2]^2-2*sum[i]*sum[j2]

    dp[j1]-dp[j2]+sum[j1]^2-sum[j2]^2>2*sum[i]*(sum[j1]-sum[j2])

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<string>
     6 #include<algorithm>
     7 int dp[500005],sum[500005],n,m,q[500005];
     8 int getup(int j,int k){
     9     return dp[j]+sum[j]*sum[j]-dp[k]-sum[k]*sum[k];
    10 }
    11 int getdown(int x,int y){
    12     return 2*(sum[x]-sum[y]);
    13 }
    14 int getdp(int i,int j){
    15     return dp[j]+m+(sum[i]-sum[j])*(sum[i]-sum[j]);
    16 }
    17 int main(){
    18     while (scanf("%d%d",&n,&m)==2){
    19     for (int i=1;i<=n;i++){
    20         scanf("%d",&sum[i]);
    21     }
    22     dp[0]=sum[0]=0;
    23     for (int i=1;i<=n;i++)
    24         sum[i]+=sum[i-1];
    25     int h=0,t=0;
    26     q[t++]=0;
    27     for (int i=1;i<=n;i++){
    28         while (h+1<t&&getup(q[h+1],q[h])<=sum[i]*getdown(q[h+1],q[h])) h++;
    29         dp[i]=getdp(i,q[h]);
    30         while (h+1<t&&getup(i,q[t-1])*getdown(q[t-1],q[t-2])<=getup(q[t-1],q[t-2])*getdown(i,q[t-1])) t--;
    31         q[t++]=i;
    32     }
    33     printf("%d
    ",dp[n]);}
    34     return 0;
    35 }
  • 相关阅读:
    二分图的最大匹配
    染色法判定二分图
    kruskal求最小生成树
    prim算法求最小生成树
    floyd
    spfa算法
    bellman_ford
    Dijkstra
    文件操作_1-18 选择题
    会话控制_2-5 编程练习
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5553677.html
Copyright © 2011-2022 走看看