解题思路

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

\[\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. 【pytorch】学习笔记(一)-张量

    pytorch入门 什么是pytorch PyTorch 是一个基于 Python 的科学计算包,主要定位两类人群: NumPy 的替代品,可以利用 GPU 的性能进行计算. 深度学习研究平台拥有足够 ...

  2. win10自带虚拟机的使用(Hyper-v)

    昨天刚发现的觉得特别好用,故推荐一下,跟VM虚拟机的使用方法是一样的 1.点击开始菜单中的<设置>图标,进入设置页码 2.点击<应用>图标,进入应用页码,并找到程序和功能 3. ...

  3. spark算子篇-aggregate 系列

    aggregate aggregate 是比较常用的 行动 操作,不是很好懂,这里做个解释. aggregate(zeroValue, seqOp, combOp) zeroValue 是一个初始值, ...

  4. GridView中点击某行的任意位置就选中该行

    GridView中点击某行的任意位置就选中该行 -- :: 分类: 第一步:添加选择列 点击GridView右边小尖头,双击CommandField,选中"选择",添加,将起设置为不可见: 第二步:处 ...

  5. powerDisgner 数据类型对比

    powerDisgner 16.5版本支持一下类型数据模型格式 以下数字数据类型可用: Standard data type DBMS-specific physical data type Cont ...

  6. CSDN添加文章目录

    在发表的文章中,系统根据文章中H1到H6标签自动生成文章目录. 一.发表文章的时候合理使用“标题”标签. 二.目录生成.只要在文章中使用了“标题1”这样的功能,就可以在博文开头看到文章的目录.

  7. docker 入门(1)

    1,docker 的安装卸载 https://docs.docker.com/install/linux/docker-ce/ubuntu/ 2,docker中的基本概念 镜像(Image) 容器(C ...

  8. HackIM web关writeup

    Web100 访问页面将看到下面的错误 在burp里使用request / response查看有没有什么不正常的地方.如下图所示,在返回的数据包里被设置了两次不同的PHPSESSID. 如果我把PH ...

  9. 关于Linux单机、集群部署FastDFS分布式文件系统的步骤。

    集群部署:2台tarcker服务器,2台storage服务器. 192.168.201.86   ---------(trackerd+storage+nginx) 192.168.201.87   ...

  10. MySQL字段值按照拼音首字母排序

    最简单.快速的方法: 将需要进行排序的字段编码设置为GBK,然后在查询时直接使用asc/desc就可以啦