数据结构优化dp

滚动数组

在dp时经常会发现只有相邻阶段间状态才会有直接联系,在转移方程中的体现形如:只有前 m 个阶段能影响当前阶段的状态,因此我们不需要储存下 n 个阶段的所有状态,只需要储存 m 个阶段的状态,以做到优化存储空间的目的。

用这种方法可以将dp某一维干掉,把 O(N) 的空间复杂度优化到常数

值域树状数组/平衡树优化dp

考虑dp方程

f[x]=min1i<xh[i]<h[x]{f[i]+w[i]}

可以将 h 数组离散化然后用树状数组维护,也可以维护平衡树来动态支持 h[i] 的插入删除

前缀和优化

单调队列

当你发现题目的转移满足这种形式时

f[x]=mini=xm+1xg[i]

也就是滑动窗口,使用单调队列是最好的选择

有些题目的转移式写出来可能不是这个形式,但是通过移项拆分,将相同变量的放到一起,可以凑出这种形式,具体可以参考后面标上单调队列建模标签的题目

ybtoj 金牌导航 递增子序列 (值域树状数组)

题目

给定 n 个数字组成的序列,问长度为 m 的严格上升子序列有多少个

1n104,1m100

题解

首先将数字离散化,然后进行dp

f[i][j] 表示以第 i 个元素结尾的长度为 j 的上升子序列的个数,那么有

f[i][j]=a[k]<a[i]k<if[k][j1]

然后你发现你要求的是值域上的一段区间,所以考虑使用树状数组优化即可

P2605 [ZJOI2010]基站选址 (线段树)

题目

N 个村庄坐落在一条直线上,第 i(i>1) 个村庄距离第 1 个村庄的距离为 Di。需要在这些村庄中建立不超过 K 个通讯基站,在第 i 个村庄建立基站的费用为 Ci。如果在距离第 i 个村庄不超过 Si 的范围内建立了一个通讯基站,那么就村庄被基站覆盖了。如果第 i 个村庄没有被覆盖,则需要向他们补偿,费用为 Wi。现在的问题是,选择基站的位置,使得总费用最小。

KNK100N20,000Di1000000000Ci10000Si1000000000Wi10000

题解

f[i][j] 表示第 j 个基站建在 i 村庄的最小费用,那么有转移

f[i][j]=mink=1i1{f[k][j1]+cost[k][i1]}+c[i]

其中 cost[i][j] 表示村庄 i 到村庄 j 的赔偿费用

由于 j 这一维连续,那么这一维可以删掉,转移方程可以改写成

f[i]=mink=1i1{f[k]+cost[k][i1]}+c[i]

这个题妙的地方来了,这里单独计算 cost[i][j] 并不容易,于是我们可以将所有 cost 代表的花费全都加在 f 数组中

具体来说,我们通过二分找出第 i 个村庄的范围是 [li,ri],那么我们在转移 i 的时候,如果上一个基站建在了 [1,li) 中,那么我们就需要给 i 支付赔偿费用,所以我们可以直接将 i 的赔偿费用,加在 f 数组中,我们可以维护一个线段树支持区间加区间求 min 就解决了这道题

时间复杂度 O(nklogn)

BZOJ3688 折线统计 (值域树状数组)

题目

题解

先将点按照横坐标大小排序

f[i][j][0/1] 表示考虑到第 i 个点,当前已经有了 j 条折线,当前折线是上升还是下降

转移如下

f[i][j][0]=k=1,yk>yii1(f[k][j][0]+f[k][j1][1])f[i][j][1]=k=1,yk<yii1(f[k][j1][0]+f[k][j][1])

然后值域树状数组优化就做完了

时间复杂度 O(nklogn)

P6089 [JSOI2015]非诚勿扰 (与极限有关的推导和树状数组求逆序对)

题目

一共有 N 位客人和 M 本书,他们都希望能够找到一本适合自己的书。

1N 的书都被编上了一个号码,并且每本书的编号不一样。

每个客人都有一个选书列表,对于每一本书,他有 p 的概率选择这本书(换言之,会以 1p 的概率拒绝这本书)。

如果他拒绝这本书,他就会去看下一本书,如果他不选最后一本书,则他又会从第一本书开始选书,直到他找到一本适合自己的书。

当然,两个客人可能选到同一本书。

在考虑任意两个不同的客人 ab ,如果 a 的编号比 b 的编号小,而 a 选择的书的编号比 b 选择的编号大,那么 ab 就叫做一对不稳定因素。

店主希望求出不稳定因素的期望数目。

1N,M5×105

题解

考虑一个人在它的列表中选第1本书的概率。假设他的列表长度为 k

g(1)=P+(1P)kP+(1P)2kP+

g(1)=P1(1P)1(1P)k=P1(1P)k

然后可以推出 g(i)=g(i1)×(1p)

最后值域树状数组求逆序对即可

时间复杂度 O(MlogN)

P7302 [NOI1998] 免费的馅饼 (排序+值域树状数组)

题目

题解

f[i] 表示考虑完前 i 个馅饼时的最大分数

转移方程为

f[i]=maxj=1i1{f[j]}+v[i]

其中

2×(t[i]t[j])| p[i]p[j] |

对绝对值分类讨论

{p[i]2×t[i]p[j]2×t[j]   (p[i]<p[j])p[i]+2×t[i]p[j]+2×t[j]   (p[i]p[j])

第一个条件排序干掉,第二个条件离散化后使用值域树状数组优化,这样就可以保证同时满足两个条件

时间复杂度为 O(nlogn)

P3287 [SCOI2014]方伯伯的玉米田 (二维树状数组)

题目

方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美。这排玉米一共有 N 株,它们的高度参差不齐。方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感的玉米拔除掉,使得剩下的玉米的高度构成一个单调不下降序列。方伯伯可以选择一个区间,把这个区间的玉米全部拔高 1 单位高度,他可以进行最多 K 次这样的操作。拔玉米则可以随意选择一个集合的玉米拔掉。问能最多剩多少株玉米,来构成一排美丽的玉米。

2N<1042K5001ai5000

题解

拔高玉米有一个显然的贪心策略:每次拔的区间都形如 [i,n],因为这样不会使得答案变劣

然后既然我们要拔高 i ,那么 i 就一定要在最终的答案序列中,不然就拔了个寂寞

f[i][j] 表示LIS以 i 为结尾,i 被拔高了 j 次最长不降子序列的长度,转移有

f[i][j]=max1ki,0lj,a[k]+la[i]+j{f[k][l]}+1

然后我们发现这东西有三维限制,我们先 for i,这一维,然后利用二维树状数组进行计算

时间复杂度 O(nklognlogk)

P2467 [SDOI2010]地精部落 (滚动数组+前缀和)

题目

1n 进行排列,排列后对于任意一个数,两边的数都比它大,或都比它小(波动序列)。求方案数

n5000

题解

这种排列的题都可以往求错排数的方向上想一想

f[i][j][0/1] 表示长度为 i 的排列结尾是 jj 是山峰/山谷的方案数

考虑转移,末尾可以再填一个 1i+1 之间的数,假设我们填的这个数是 j,那么有转移

f[i][j][0]=k=1j1f[i1][k][1]f[i][j][1]=k=j+1if[i1][k][0]

滚动数组滚掉第一位维,前缀和优化第二维即可

时间复杂度 O(n2)

ybtoj 金牌导航 最大连续和 (单调队列)

题目

给定一个长度为 n 的序列 a ,要求从中找到一段连续的长度不超过 m 的子序列,使得这个序列的和最大, a 可以为负

n,m2×106

题解

f[i] 表示以 a[i] 结尾长度不超过 m 的最大子序列和,那么有转移

f[i]=max1km{j=ik+1iaj}

首先使用前缀和优化掉求和,我们把前缀和存在 pre 数组中,那么转移式变为

f[i]=pre[i]min1km{pre[ik]}

那么后面的那个 min 就变成了滑动窗口的形式,单调队列优化即可

时间复杂度 O(n)

ybtoj 金牌导航 修剪草坪 (单调队列)

题目

有一个长度为 N 的数列,我们现在要从序列中选取一些数,但是不能连续取超过 K 个数,问选取的数字之和最大是多少

1N1×105

题解

f[i][0/1] 表示考虑到第 i 个数,当前数不选/选时的最大和,转移方程如下

{f[i][1]=maxikji1{f[j][0]+pre[i]pre[j]}f[i][0]=max{f[i1][0],f[i1][1]}

单调队列优化即可

时间复杂度 O(n)

ybtoj 金牌导航 旅行问题 (单调队列建模)

题目

John 打算驾驶一辆汽车周游一个环形公路。公路上总共有 n 车站,每站都有若干升汽油(有的站可能油量为零),每升油可以让汽车行驶一千米。John 必须从某个车站出发,一直按顺时针(或逆时针)方向走遍所有的车站,并回到起点。在一开始的时候,汽车内油量为零,John 每到一个车站就把该站所有的油都带上(起点站亦是如此),行驶过程中不能出现没有油的情况。

判断以每个车站为起点能否按条件成功周游一周。

3n106

题解

先破环成链,链的长度为 2n 然后考虑顺时针的情况

对汽车油量和距离分别做前缀和 s1,s2,如果从第 i 个点出发可以回到起点,就意味着在 [i,i+n1] 的区间内,满足所有油量与距离之差的前缀和都大于等于 0,即满足

(s1[j]s1[i1])(s2[j]s2[i1])0(j[i,i+n1])

这个东西是很难维护的,所以我们可以尝试对汽车油量与距离之差做前缀和,记为 s

算出 s 数组后,我们就可以求区间最小值减去 s[i1]0 作比较,问题转化成了滑动窗口

逆时针同理,时间复杂度 O(n)

单调队列优化多重背包 (单调队列建模)

题目

我们现在有 n 个物品,第 i 物品有三个属性:个数 si 重量 vi 和价值 wi 现在求出在背包容量是 k 的情况可以收获的最大价值

n107

题解

通过01背包的状态,我们很容易写出这个问题一般的转移方程

dp[i][j]=max(dp[i-1][j],dp[i-1][j-v]+w,dp[i-1][j-2*v]+2*w,.....,dp[i-1][j-s*v]+s*w)

滚动数组优化下变成

dp[j]=max(dp[j],dp[j-v]+w,dp[j-2*v]+2*w,.....,dp[j-s*v]+s*w)

由此我们发现 j 只与与 v 同余的位置有关,因此我们可以将同余的视作一组,那么这样一共有 k 组,这样我们的转移方程就可以写成下面这样

dp[j]=dp[j]
dp[j+v]=max(dp[j]+w,dp[j+v])
dp[j+2v]=max(dp[j]+2w,dp[j+v]+w,dp[j+2v])
dp[j+3v]=max(dp[j]+3w,dp[j+v]+2w,dp[j+2v]+w,dp[j+3v])
.....

对它进行一个变形

dp[j]=dp[j]
dp[j+v]=max(dp[j],dp[j+v]-w)+w
dp[j+2v]=max(dp[j],dp[j+v]-w,dp[j+2v]-2w)+2w
dp[j+3v]=max(dp[j],dp[j+v]-w,dp[j+2v]-2w,dp[j+3v]-3w)+3w
......

这样变形的意义在于,我们将原先不规则的、难以维护的东西转换成了规则的,好维护的东西。换句话说,我们要知道 j+k×v 的答案,我们只需要把 dp[j+k×v]k×w 和前 k1 个相同格式的东西进行比较,这样我们就可以使用单调队列来维护最大值了

时间复杂度 O(nk)

P2254 [NOI2005] 瑰丽华尔兹

题目

给定一个 n×m 大小的矩阵,起点是 (x,y) 。给你 k 段时间,对于第 i 段时间 [si,ti] ,在该时间中你可以以 1单位/s 的速度在 di 方向上运动,不能走到障碍物上,问能够运动的最远距离是多少

n,m200,k200

题解

f[i][x][y] 表示考虑到第 i 段时间,结束后走到 x,y 这个格子的最远距离

直接暴力转移的复杂度是 O(knm(n+m)) 的,我们无法接受

思考一下这个东西是怎么转移的,我们发现这个转移是关于最值的,而且只关系到某一行/列,是线性的,这时候就不妨向单调队列的方向想一想

注意到对于当前时间段 i ,假设它的长度是 len ,那么能够转移到点 (x,y) 上的状态实际就处在一个长度为 len 的窗口中

所以我们就可以使用单调队列优化干掉一维,时间复杂度 O(knm)

P2216 [HAOI2007]理想的正方形

题目

有一个 a×b 的整数组成的矩阵,现请你从中找出一个 n×n 的正方形区域,使得该区域所有数中的最大值和最小值的差最小。

2a,b1000,na,nb,n100

题解

利用单调队列,将原来 a×b 的矩阵中的数,先将行上的最大值最小值按照 n 个一组压到一个 (an+1)×b 的矩阵中,然后在将压完后的矩阵中的数再拿出来,按列压到一个 (an+1)×(bn+1) 的矩阵中

时间复杂度 O(ab)

P2569 [SCOI2010]股票交易 (单调队列建模)

题目

你初始时有无限的钱,并且每天持有的股票不超过 Maxp 。 有 T 天,你知道每一天的买入价格( AP[i] ),卖出价格( Bp[i] ), 买入数量限制( AS[i] ),卖出数量限制( BS[i] )。 并且两次交易之间必须间隔 W 天。 现在问你 T 天结束后,最大收益是多少

1BPiAPi1000,1ASi,BSiMaxP,T2000,MaxP2000

题解

f[i][j] 表示前 i 天之后,剩下 j 股股票的最大收益

状态转移方程如下

买入:

f[i][j]=maxjas[i]kj(f[iw1][k](jk)×ap[i])

卖出:

f[i][j]=maxjkj+bs[i](f[iw1][k]+(kj)×bp[i])

复杂度是 O(TMaxp2) ,无法通过本题,考虑优化

同样的套路,将具有相同变量的东西放在一起

f[iw1][k]+(kj)×bp[i]=(f[iw1][k]+k×bp[i])j×bp[i]

我们将 j×bp[i] 提到括号外边去,内部就变成了一个滑动窗口,直接单调队列优化即可

时间复杂度 O(TMaxp)

posted on   star_road_xyz  阅读(67)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示