正睿国庆DAY2动态规划专题
排列-例题
-
1~n 的排列个数,每个数要么比旁边两个大,要么比旁边两个小
(f[i][j]) 填了前i个数,未填的数有(j)个比第(i)个小,是波峰
(g[i][j])是波谷
(f[i][j] -g[i+1][j'])
(g[i][j]-f[i+1][j'])
可以前缀和优化
-
n个数的排列中恰好有k个位置满足(a_i<a_{i+1})的个数
可能是今天唯一自己想出来的题了23333
(f[i][j]) 前i个数的排列有j个小于号的排列个数,并考虑插入第(i+1)个数
放最前面:(f[i][j]->f[i+1][j])
放中间的小于号 :(j*f[i][j] -> f[i+1][j])
放中间的大于号 :((i-1-j)*f[i][j] -> f[i+1][j+1])
放最后面:(f[i][j]->f[i][j-1])
然后可以搞组合计数优化
排列dp的处理总结:
- 枚举个数/剩余个数
- 插入法(通常更优)
优化复杂度
状态数
- 合理设计
- 去掉没有用的状态
转移
- 前缀和
- 数据结构优化
- 矩阵优化(递推)
- trivival -> non-trivival (改掉某些转移,便乘不显然的形式)
优化空间
- 滚动数组
继续例题
-
f[i]为(1- i)被覆盖的最小代价,用树状数组维护区间(f)最小值就可以了
-
即每行选一个数使得和最大
- 普通dp: (3^n*m)
- 每一列只需要考虑前n个最大的
- 考虑每列循环移位同样的步数答案都一样,可以优化成(2^nn^2)
-
(n) 个数排列中恰好有 (k) 个峰的方案数,(pmod {239})
(nleq 10^{15},kleq 30)
(f[i][j]) 前(i)个数,有(j)个峰,考虑添加第(i+1)个数
-
搞掉前面的一个峰:(f[i+1][j]+=f[i][j]*2j)
-
否则(f[i+1][j+1]+=f[i][j]*(i+1-2*j))
可以写成矩阵乘法,且(M_i=M_i+239)
-
四点半之后突然颓(看大佬博客),少听两道题