解题思路

首先肯定是考虑如何快速求出一段铁路的价值。

\[\sum_{i=1}^k \sum_{j=1, j\neq i}^kA[i]A[j]=(\sum_{i=1}^kA[i])^2-\sum_{i=1}^kA[i]^2
\]

那么我们要维护如下两个东西,就可以在\(O(1)\)内求出一段铁路的价值了。

for( LL i = 1; i <= N; ++i ) Sum[ i ] = Sum[ i - 1 ] + A[ i ];
for( LL i = 1; i <= N; ++i ) SumOfSqr[ i ] = SumOfSqr[ i - 1 ] + A[ i ] * A[ i ];

然后我们考虑打一个最暴力的DP。

我们令\(F[i][j]\)为到第\(i\)个仓库,炸了\(j\)次的最小总价值:

for( LL i = 1; i <= N; ++i )
F[ i ][ 0 ] = Sum[ i ] * Sum[ i ] - SumOfSqr[ i ];
for( LL j = 1; j <= M; ++j )
for( LL i = j + 1; j <= N; ++j ) {
F[ i ][ j ] = INF;
for( LL k = j; k < i; ++k )
F[ i ][ j ] = min( F[ i ][ j ], F[ k ][ j - 1 ] + sqr( Sum[ i ] - Sum[ k ] ) - ( SumOfSqr[ i ] - SumOfSqr[ k ] ) );
}
Ans = F[ N ][ M ];

为了节省空间,我们滚动掉一维:

for( LL i = 1; i <= N; ++i )
F1[ i ] = Sum[ i ] * Sum[ i ] - SumOfSqr[ i ];
for( LL j = 1; j <= M; ++j ) {
for( LL i = j + 1; j <= N; ++j ) {
F2[ i ] = INF;
for( LL k = j; k < i; ++k )
F2[ i ] = min( F2[ i ], F1[ k ] + sqr( Sum[ i ] - Sum[ k ] ) - ( SumOfSqr[ i ] - SumOfSqr[ k ] ) );
}
memcpy( F1, F2, sizeof( F2 ) );
}
Ans = F1[ N ];

最后考虑优化转移复杂度:

设\(l > k\),且从\(l\)转移优于从\(k\)转移,那么就有:

\[F_1[l]+(S[i]-S[l])^2-(SOS[i]-SOS[l])<F_1[k]+(S[i]-S[k])^2-(SOS[i]-SOS[k])
\]

\[(F_1[l]+S[l]^2+SOS[l])-(F_1[k]+S[k]^2+SOS[k])<2S[i](S[k]-S[l])
\]

\[\frac{(F_1[l]+S[l]^2+SOS[l])-(F_1[k]+S[k]^2+SOS[k])}{2S[l]-2S[k]}<S[i]
\]

然后我们就可以进行斜率优化了。

斜率优化的具体讲解见这里

参考程序

#include <bits/stdc++.h>
#define LL long long
using namespace std; const LL Maxn = 1010;
LL n, m;
LL A[ Maxn ], Sum[ Maxn ], SumOfSqr[ Maxn ], F1[ Maxn ], F2[ Maxn ];
LL L, R, Queue[ Maxn ]; inline LL Sqr( LL x ) { return x * x; } inline LL GetSum( LL r, LL l ) {
return Sqr( Sum[ r ] - Sum[ l ] ) - ( SumOfSqr[ r ] - SumOfSqr[ l ] );
} inline bool Less( LL i, LL j, LL T ) {
LL X = 2 * ( Sum[ j ] - Sum[ i ] );
LL Y = ( F1[ j ] + Sqr( Sum[ j ] ) + SumOfSqr[ j ] ) -
( F1[ i ] + Sqr( Sum[ i ] ) + SumOfSqr[ i ] );
return Y < T * X;
} inline bool Greater( LL i, LL j, LL k ) {
LL X1 = 2 * ( Sum[ j ] - Sum[ i ] );
LL Y1 = ( F1[ j ] + Sqr( Sum[ j ] ) + SumOfSqr[ j ] ) -
( F1[ i ] + Sqr( Sum[ i ] ) + SumOfSqr[ i ] );
LL X2 = 2 * ( Sum[ k ] - Sum[ j ] );
LL Y2 = ( F1[ k ] + Sqr( Sum[ k ] ) + SumOfSqr[ k ] ) -
( F1[ j ] + Sqr( Sum[ j ] ) + SumOfSqr[ j ] );
return X2 * Y1 >= X1 * Y2;
} void Work() {
for( LL i = 1; i <= n; ++i ) scanf( "%lld", &A[ i ] );
Sum[ 0 ] = 0; SumOfSqr[ 0 ] = 0;
for( LL i = 1; i <= n; ++i ) Sum[ i ] = Sum[ i - 1 ] + A[ i ];
for( LL i = 1; i <= n; ++i ) SumOfSqr[ i ] = SumOfSqr[ i - 1 ] + Sqr( A[ i ] );
for( LL i = 1; i <= n; ++i )
F1[ i ] = GetSum( i, 0 );
for( LL j = 1; j <= m; ++j ) {
L = R = 0; Queue[ R++ ] = j;
memset( F2, 0, sizeof( F2 ) );
for( LL i = j + 1; i <= n; ++i ) {
while( L + 1 < R && Less( Queue[ L ], Queue[ L + 1 ], Sum[ i ] ) )
++L;
F2[ i ] = F1[ Queue[ L ] ] + GetSum( i, Queue[ L ] );
while( L + 1 < R && Greater( Queue[ R - 2 ], Queue[ R - 1 ], i ) )
--R;
Queue[ R++ ] = i;
}
memcpy( F1, F2, sizeof( F2 ) );
}
printf( "%lld\n", F1[ n ] / 2 );
return;
} int main() {
scanf( "%lld%lld", &n, &m );
while( !( n == 0 && m == 0 ) ) {
Work();
scanf( "%lld%lld", &n, &m );
}
return 0;
}

HDU 2829 [Lawrence] DP斜率优化的更多相关文章

  1. HDU.2829.Lawrence(DP 斜率优化)

    题目链接 \(Description\) 给定一个\(n\)个数的序列,最多将序列分为\(m+1\)段,每段的价值是这段中所有数两两相乘的和.求最小总价值. \(Solution\) 写到这突然懒得写 ...

  2. HDU 2829 Lawrence(斜率优化DP O(n^2))

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2829 题目大意:有一段铁路有n个站,每个站可以往其他站运送粮草,现在要炸掉m条路使得粮草补给最小,粮草 ...

  3. HDU 3480 Division DP斜率优化

    解题思路 第一步显然是将原数组排序嘛--然后分成一些不相交的子集,这样显然最小.重点是怎么分. 首先,我们写出一个最暴力的\(DP\): 我们令$F[ i ][ j ] $ 为到第\(i\)位,分成\ ...

  4. hdu 2829 Lawrence(四边形不等式优化dp)

    T. E. Lawrence was a controversial figure during World War I. He was a British officer who served in ...

  5. HDU 2829 Lawrence (斜率DP)

    斜率DP 设dp[i][j]表示前i点,炸掉j条边的最小值.j<i dp[i][j]=min{dp[k][j-1]+cost[k+1][i]} 又由得出cost[1][i]=cost[1][k] ...

  6. hdu 2829 Lawrence(斜率优化DP)

    题目链接:hdu 2829 Lawrence 题意: 在一条直线型的铁路上,每个站点有各自的权重num[i],每一段铁路(边)的权重(题目上说是战略价值什么的好像)是能经过这条边的所有站点的乘积之和. ...

  7. HDU 2829 区间DP & 前缀和优化 & 四边形不等式优化

    HDU 2829 区间DP & 前缀和优化 & 四边形不等式优化 n个节点n-1条线性边,炸掉M条边也就是分为m+1个区间 问你各个区间的总策略值最少的炸法 就题目本身而言,中规中矩的 ...

  8. HDU 3507 [Print Article]DP斜率优化

    题目大意 给定一个长度为\(n(n \leqslant 500000)\)的数列,将其分割为连续的若干份,使得 $ \sum ((\sum_{i=j}^kC_i) +M) $ 最小.其中\(C_i\) ...

  9. HDU 3507 单调队列 斜率优化

    斜率优化的模板题 给出n个数以及M,你可以将这些数划分成几个区间,每个区间的值是里面数的和的平方+M,问所有区间值总和最小是多少. 如果不考虑平方,那么我们显然可以使用队列维护单调性,优化DP的线性方 ...

随机推荐

  1. UML表示类图和对象图

    类图表示不同的实体(人.事物和数据)如何彼此相关,显示了系统的静态结构.类图可用于表示逻辑类,逻辑类通常就是业务人员所谈及的事物种类,比如摇滚乐队.CD.广播剧,或者贷款.住房抵押.汽车信贷及利率的抽 ...

  2. [LGP4859,...] 一类奇怪的容斥套DP

    漫山遍野都是fake的光影. 题目 [LGP4859] 已经没有什么好害怕的了 给定两个长度为n的数组a和b,将a中元素与b中元素配对,求满足ai>bj的配对(i,j)个数减去满足ai<b ...

  3. Laravel-admin form 表单是增加或者修改

    Laravel-admin 实现 form 表单是增加或者修改的三种方法,应用情景:1.新增或者修改 form 展示的表单不同:2.新增或者保存前后回调进行其他的操作 1. use Illuminat ...

  4. Python 入门 之 初识面向对象

    Python 入门 之 初识面向对象 1.初识面向对象编程 (核心--对象) (1)观察以下代码: # 面向过程编程 s = "alexdsb" count = 0 for i i ...

  5. spring boot jpa @PreUpdate结合@DynamicUpdate使用的局限性

    通常给实体添加audit审计字段是一种常用的重构方法,如下: @Embeddable @Setter @Getter @ToString public class Audit { /** * 操作人 ...

  6. webAapi

    学习目标: 掌握API和Web API的概念 掌握常见浏览器提供的API的调用方式 能通过Web API开发常见的页面交互功能 能够利用搜索引擎解决问题 typora-copy-images-to: ...

  7. oppo 手机不能连接appium,提示does not have permission android.permission.CLEAR_APP_USER_DATA to clear data

    1)增加配置项noReset=true 2)除了常见开发者选项中打开usb调试,同时还需要开启以下2项,然后重启手机即可

  8. 【Java】 Java网络编程总结

     一.网络编程三要素: IP地址:每个设备在网络中的唯一标识. 端口号:每个程序在设备上的唯一标识. 协议:为计算机网络中进行数据交换而建立的规则或约定的集合. UDP: 面向无连接,数据不安全,速度 ...

  9. java对象只有值传递,为什么?

    在开始深入讲解之前,有必要纠正一下大家以前的那些错误看法了.如果你有以下想法,那么你有必要好好阅读本文. 错误理解一:值传递和引用传递,区分的条件是传递的内容,如果是个值,就是值传递.如果是个引用,就 ...

  10. 本地安装Mysql后,navicat链接异常:Clinet dose not support authentication protocol request by server ; consider upgrading MySQL client

    第一步:首先通过cmd进入mysql 在命令窗口 输入:mysql -u root -p: 第二步:更改加密方式 mysql> ALTER USER 'root'@'localhost' IDE ...