DP优化
调试DP:把他们都打印出来,脑袋清醒地想初始值和转移条件(边界)
简单优化
先写出朴素做法再思考优化
关于绝对值, 我们要考虑拆掉绝对值来做
T1
你要构造一个长度为N的数列,数列的元素在1和M之间,如果数列相邻两个数变化比较小,你会感到无聊,所以你希望相邻两个数的差不小于K。
求满足要求的方案数
考虑一下阶段, 线性dp有两个天然的阶段,时间和事件, 影响无非就是前一个数选的啥
所以设f[i][j]表示前i-1个数选好, 第i个数填j的方案数
转移 f[i][j] += f[i-1][x] (x满足|x - j| >= K)
若x >= j 则为 f[i - 1][x] 满足x >= j + K
若x < j 则为 f[i - 1][x] 满足x <= j - K
我们发现求一下前缀和, 后缀和就可以O(1)转移了
T2 取龙珠 link
考虑影响无非就是上一轮在哪个地方, 耗费是多少
// m个时间(阶段) 每个时间有n颗龙珠 初始在x
// 第i个时间段,第j颗龙珠的位置
// f[i][j] 表示拿完1~i-1的龙珠, 第i次拿第j颗龙珠的最小花费
// 显然有f[i][j] = min(f[i-1][k] + (k到j的花费)) + cost[j]
k -> j 花费为 |pos[k] - pos[j]|
所以我们考虑分讨 若 pos[k] >= pos[j]
那么 = min(f[i-1][k] + pos[k]) + cost[j] - pos[j]
我们发现求的又是一个后缀的最小值
另一种情况同理
注意后缀最小值是建立在pos[k] >= pos[j]的基础上的 所以得排个序
abc353G link
首先发现一个性质就是, 对于一个我们不可能走到一个没用的点上
所以有效的状态就n个
可以设f[i]为参加第i次集会的最大收益
那么转移就是f[i] = max(f[k] + |pos[k] - pos[i]|) + val[i]
若pos[k] >= pos[i]
那么有 max(f[k] + pos[k]) - pos[i] + val[i]
就是在求后缀最大值, 那么这个题可以排序吗, 显然是不可以
做法类似BIT优化LIS
有意思的就是BIT求后缀信息
poi小鸟 link
状态是显然的f[i]表示到第i个点的最小花费
那么有显然的转移就是 f[i] = min(f[k] + (d[k] <= d[i])) (k ∈ [i - K, i - 1])
那么考虑有哪些无效的状态 不难发现若f[i + 1] < f[i] 则f[i]无用, 因为即使i的高度更大, 那么i + 1也只需要加1转移并不劣
就是f[i] == f[i + 1]时那么高的树更有优势, 这个可以单调队列维护
好题 cf960f link
两种思路
1.BIT优化LIS (动态开点线段树)
f[i]表示以i这条边结尾的最长图上LIS
朴素
rep(i, 1, m) rep(j, 1, m)
if(edge[i].val < edge[j].val && edge[i].to == edge[j].from)
f[j] = max(f[j], f[i] + 1)
比普通lis多了一条限制就是收尾相连
所以很直观的优化就是开n颗动态开点线段树,用法类似优化lis的BIT,就是在form里面查询比e[j].val小的最长lis转移。
2.贪心加二分优化LIS
讲的非常好的一篇 link

浙公网安备 33010602011771号