首页 > 其他分享 >数据结构优化dp

数据结构优化dp

时间:2023-07-24 20:14:20浏览次数:39  
标签:le text 复杂度 times max 数据结构 优化 dp

滚动数组

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

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

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

考虑dp方程

\[f[x]=\min_{1\le i<x\text{且}h[i]<h[x]} \{f[i]+w[i]\} \]

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

前缀和优化

单调队列

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

\[f[x]=\min_{i=x-m+1}^xg[i] \]

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

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

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

题目

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

\(1\le n\le 10^4,1\le m\le 100\)

题解

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

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

\[f[i][j]=\sum_{a[k]<a[i]}^{k<i}f[k][j-1] \]

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

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

题目

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

\(K\leq N\),\(K\leq 100\),\(N\leq 20,000\),\(D_i \leq 1000000000\),\(C_i\leq 10000\),\(S_i \leq1000000000\),\(W_i \leq 10000\)。

题解

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

\[f[i][j]=\min_{k=1}^{i-1}\{f[k][j-1]+\text{cost}[k][i-1]\}+c[i] \]

其中 \(\text{cost}[i][j]\) 表示村庄 \(i\) 到村庄 \(j\) 的赔偿费用

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

\[f[i]=\min_{k=1}^{i-1}\{f[k]+\text{cost}[k][i-1]\}+c[i] \]

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

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

时间复杂度 \(\mathcal O(nk\log n)\)

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

题目

题解

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

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

转移如下

\[f[i][j][0]=\sum_{k=1,y_k>y_i}^{i-1}(f[k][j][0]+f[k][j-1][1])\\f[i][j][1]=\sum_{k=1,y_k<y_i}^{i-1}(f[k][j-1][0]+f[k][j][1]) \]

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

时间复杂度 \(O(nk\log n)\)

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

题目

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

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

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

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

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

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

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

\(1\le N,M\le 5\times 10^5\)

题解

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

\[g(1)=P+(1−P)^kP+(1−P)^{2k}P+\cdots \]

\[g(1)=P\frac{1-(1-P)^\infty}{1-(1-P)^k}=\frac{P}{1-(1-P)^k} \]

然后可以推出 \(g(i)=g(i-1)\times (1-p)\)

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

时间复杂度 \(\mathcal O(M\log N)\)

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

题目

题解

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

转移方程为

\[f[i]=\max_{j=1}^{i-1} \{f[j]\}+v[i] \]

其中

\[2 \times (t[i]-t[j]) \ge |\ p[i]-p[j]\ | \]

对绝对值分类讨论

\[\begin{cases} p[i]-2 \times t[i] \le p[j]-2 \times t[j] ~~~(p[i] \lt p[j])\\ p[i]+2 \times t[i] \ge p[j]+2 \times t[j] ~~~(p[i]\ge p[j]) \end{cases} \]

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

时间复杂度为 \(O(n\log n)\)

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

题目

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

$2 \le N \lt 10^4 $,\(2 \le K \le 500\),\(1 \leq a_i \leq 5000\)。

题解

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

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

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

\[f[i][j]=\max_{1\le k\le i,0\le l\le j,a[k]+l\le a[i]+j}\{f[k][l]\}+1 \]

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

时间复杂度 \(\mathcal O(nk\log n\log k)\)

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

题目

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

\(n\le 5000\)

题解

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

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

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

\[f[i][j][0]=\sum_{k=1}^{j-1}f[i-1][k][1]\\f[i][j][1]=\sum_{k=j+1}^{i}f[i-1][k][0] \]

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

时间复杂度 \(\mathcal O(n^2)\)

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

题目

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

\(n,m\le 2\times 10^6\)

题解

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

\[f[i]=\max_{1\le k\le m}\{\sum_{j=i-k+1}^{i}a_j\} \]

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

\[f[i]=\text{pre}[i]-\min_{1\le k\le m} \{\text{pre}[i-k]\} \]

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

时间复杂度 \(\mathcal O(n)\)

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

题目

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

\(1\le N\le 1\times 10^5\)

题解

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

\[\begin{cases} f[i][1]=\max_{i-k\le j\le i-1}\{f[j][0]+\text{pre}[i]-pre[j]\}\\f[i][0]=\max\{f[i-1][0],f[i-1][1]\} \end{cases} \]

单调队列优化即可

时间复杂度 \(\mathcal O(n)\)

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

题目

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

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

\(3 \le n\le 10^6\)

题解

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

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

\[(s_1[j]-s_1[i-1])-(s_2[j]-s_2[i-1])\geqslant 0\,\,\,(j\in [i, i+n-1]) \]

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

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

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

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

题目

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

\(n\le 10^7\)

题解

通过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\times v\) 的答案,我们只需要把 \(\text{dp}[j+k\times v]-k\times w\) 和前 \(k-1\) 个相同格式的东西进行比较,这样我们就可以使用单调队列来维护最大值了

时间复杂度 \(\mathcal O(nk)\)

P2254 [NOI2005] 瑰丽华尔兹

题目

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

\(n,m\le 200,k\le 200\)

题解

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

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

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

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

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

P2216 [HAOI2007]理想的正方形

题目

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

\(2 \le a,b \le 1000,n \le a,n \le b,n \le 100\)。

题解

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

时间复杂度 \(\mathcal O(ab)\)

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

题目

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

\(1\leq BP_i\leq AP_i\leq 1000,1\leq AS_i,BS_i\leq\text{MaxP},T\le 2000,\text{MaxP}\le 2000\)

题解

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

状态转移方程如下

买入:

\[f[i][j]=\max_{j-as[i]\le k\le j}(f[i-w-1][k]-(j-k)\times ap[i]) \]

卖出:

\[f[i][j]=\max_{j\le k\le j+bs[i]}(f[i-w-1][k]+(k-j)\times bp[i]) \]

复杂度是 \(\mathcal O(T\text{Maxp}^2)\) ,无法通过本题,考虑优化

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

\[f[i-w-1][k]+(k-j)\times bp[i]=(f[i-w-1][k]+k\times bp[i])-j\times bp[i] \]

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

时间复杂度 \(\mathcal O(T\text{Maxp})\)

标签:le,text,复杂度,times,max,数据结构,优化,dp
From: https://www.cnblogs.com/starroadxyz/p/17578210.html

相关文章

  • 线性 DP、背包问题、区间 DP 学习笔记
    动态规划基础知识基本概念动态规划:解决多阶段决策过程最优化问题的一种方法。阶段:把问题分解成相互联系的有顺序的几个环节,这些环节即成为阶段。状态:某一阶段的出发位置称为状态。通常一个阶段包含若干状态。决策:从某阶段的一个状态演变到下一个阶段某状态的选择。策略:由开......
  • JavaScript数据结构和算法简述——数组
    为什么先讲数组数据结构可以简单的被分为线性结构和非线性结构。线性结构大致包括:数组(连续存储);链表(离散存储);栈(线性结构常见应用,由链表或数组增删和改进功能实现);队列(线性结构常见应用,由链表或数组增删和改进功能实现);非线性结构大致包括:树;图;其中,数组是应用最广泛的数据存储结构。它被......
  • 7.24 day1数据结构
    day1数据结构考试整场比赛打完了,没用数据结构?!结果:100+30+40+30=200T1正解异或好性质,100000以下最多128个因数枚举每个右端点,将前缀异或塞进桶里,同时枚举因数,看有几个和自己对应的前缀异或,直接计数即可T2暴力要输出分数,考场实在没办法,用浮点数做01分数规划,最后枚举分母(只......
  • 性能优化
    1.图片懒加载:1.vue插件 vue-lazyload           2.element-ui 可开启图片懒加载功能加上lazy           3.使用IntersectionObserverApi监听某些节点是否出现在可视区域内           4.offsetTop(图......
  • 【智能优化算法】基于黄金莱维引导机制的阿基米德优化算法(MSAOA)求解单目标优化问题
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • m基于DVB-T的COFDM+16QAM+LDPC码通信链路matlab性能仿真,包括载波同步,定时同步,信道
    1.算法仿真效果matlab2022a仿真结果如下:包括小数倍及整数倍载波同步,粗及细定时同步2.算法涉及理论知识概要基于DVB-T的COFDM+16QAM+LDPC码通信链路是一种常用的数字视频广播系统,用于实现高效的传输和接收。该系统结合了正交频分复用(COFDM)、16QAM调制和低密度奇偶校验(LDPC)编码......
  • 【BP分类】基于遗传算法优化BP神经网络的数据分类附matlab代码
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • m基于OFDM+QPSK和LDPC编译码通信链路matlab性能仿真,包括Costas载波同步和gardner定时
    1.算法仿真效果matlab2013b仿真结果如下:      2.算法涉及理论知识概要        基于OFDM+QPSK和LDPC编码的通信链路是一种常用的数字通信系统,用于实现高速、可靠的数据传输。该系统结合了正交频分复用(OFDM)、四相移键控(QPSK)调制和低密度奇偶校验(LDPC)编码......
  • m基于DVB-T的COFDM+16QAM+LDPC码通信链路matlab性能仿真,包括载波同步,定时同步,信道
    1.算法仿真效果matlab2022a仿真结果如下: 包括小数倍及整数倍载波同步,粗及细定时同步     2.算法涉及理论知识概要        基于DVB-T的COFDM+16QAM+LDPC码通信链路是一种常用的数字视频广播系统,用于实现高效的传输和接收。该系统结合了正交频分复用(CO......
  • DPI数据挖掘
    DPI数据挖掘的流程对于一位刚入行的小白来说,实现"DPI数据挖掘"可能是一项具有挑战性的任务。下面我将向你介绍整个流程,并提供每一步所需的代码及其注释,帮助你完成这个任务。步骤下表展示了"DPI数据挖掘"的步骤及其大致顺序:步骤描述1.数据收集收集需要进行数据挖掘的......