P2331 [SCOI2005 ]最大子矩阵
根据数据特性分类
P4158 [SCOI2009]粉刷匠
所有格子都涂色不影响答案
最小化单元 设定状态 转换为多行线性dp+处理行首与上一行行末边界
最后一维代表这一次粉刷的颜色
P1169 [ZJOI2007]棋盘制作
悬线法 枚举前几行压缩为线性问题
限制1:悬线法本身高度
限制2: 题目要求
P1040 [NOIP2003 提高组] 加分二叉树
中序遍历已知–>区间dp
凸多边形的划分
环形区间dp 用点作为区间
简单瞎搞题
bitset优化背包板子
打砖块(brike)
一层一层dp 前一层需要设定的状态较多
考虑对一列一列进行dp
对于某一列 选择的打掉的砖块一定是连续且从第一层开始的
对于前一列 当前列选择的砖块数
>
=
>=
>=前一列选择的砖块数
−
1
-1
−1
d
p
i
j
k
dp_{i j k}
dpijk 表示前
i
i
i 列,共选了
j
j
j 个砖块,且当且列选了
k
k
k 个砖块的合法方案的最大值
CF229D Towers
转换为一个分区间的dp问题,然后要保证分出来的前一个区间和小于后一个区间和,区间分得越多越好
d
p
i
=
d
p
j
+
(
i
−
j
−
1
)
dp_{i}=dp_{j}+(i-j-1)
dpi=dpj+(i−j−1) 满足:
s
u
m
j
−
s
u
m
k
<
=
s
u
m
i
−
s
u
m
j
sum_{j}-sum_{k}<=sum_{i}-sum_{j}
sumj−sumk<=sumi−sumj
d
p
i
dp_i
dpi表示前
i
i
i个数划分区间后的最小操作数
分析这个式子
性质一:
j
j
j越大,
d
p
j
+
(
i
−
j
−
1
)
dp_{j}+(i-j-1)
dpj+(i−j−1)最小。
证明:假设有一个
x
<
j
x<j
x<j,
d
p
j
<
=
d
p
x
+
j
−
x
dp_j<=dp_x+j-x
dpj<=dpx+j−x
d
p
x
+
(
i
−
x
−
1
)
=
d
p
x
+
(
j
−
x
)
+
(
i
−
j
−
1
)
>
=
d
p
j
+
(
i
−
j
−
1
)
dp_x+(i-x-1)=dp_x+(j-x)+(i-j-1)>=dp_j+(i-j-1)
dpx+(i−x−1)=dpx+(j−x)+(i−j−1)>=dpj+(i−j−1)
性质二:转移方程中的
k
k
k就是
d
p
j
dp_j
dpj之前的最优转移点,
j
j
j与
k
k
k的关系类似于
i
i
i与
j
j
j的关系。
证明:因为我们每次会找离
i
i
i最近的
j
j
j进行转移,那么之前转移到
j
j
j这个状态时,假设
j
j
j之前满足条件的点是
k
1
<
k
2
<
k
3
<
.
.
.
.
<
k
n
k1<k2<k3<....<kn
k1<k2<k3<....<kn,那么想要满足这个式子
s
u
m
j
−
s
u
m
k
<
=
s
u
m
i
−
s
u
m
j
sum_{j}-sum_{k}<=sum_{i}-sum_{j}
sumj−sumk<=sumi−sumj,贪心的想:
k
k
k越大越好,那么
k
n
kn
kn即
j
j
j的最佳转移点,也是
i
,
j
i,j
i,j已经确定,能否满足式子最优情况
由性质一和二:
p
r
e
i
pre_{i}
prei代表
d
p
i
dp_i
dpi由
d
p
p
r
e
i
dp_{pre_i}
dpprei转移过来
那么对于一个
i
i
i,从后往前枚举
j
j
j,知道第一个满足
s
u
m
j
−
s
u
m
p
r
e
j
<
=
s
u
m
i
−
s
u
m
j
sum_{j}-sum_{pre_j}<=sum_{i}-sum_{j}
sumj−sumprej<=sumi−sumj
的
j
j
j即完成转移,并令
p
r
e
i
=
j
pre_i=j
prei=j
O(n)方法待补
CF1110D Jongmah
d
p
i
,
j
,
k
dp_{i,j,k}
dpi,j,k表示到
i
i
i 这个数时,
i
−
1
,
i
,
i
+
1
i-1,i,i+1
i−1,i,i+1的三元组有
j
j
j个,
i
,
i
+
1
,
i
+
2
i,i+1,i+2
i,i+1,i+2有
k
k
k的三元组有
k
k
k个的状态下,组成的三元组数最大值
暴力转移很简单:
d
p
i
+
1
,
k
,
l
=
m
a
x
(
d
p
i
,
j
,
k
+
(
s
u
m
i
+
1
−
j
−
k
−
l
)
/
3
+
l
)
dp_{i+1,k,l}=max(dp_{i,j,k}+(sum_{i+1}-j-k-l)/3+l)
dpi+1,k,l=max(dpi,j,k+(sumi+1−j−k−l)/3+l)
通过题目知道 j , k j,k j,k最多为2,如果连续三元组 i − 1 , i , i + 1 i-1,i,i+1 i−1,i,i+1数多于2,可以等效替代为多个 i − 1 , i − 1 , i − 1 i-1,i-1,i-1 i−1,i−1,i−1和 i , i , i i,i,i i,i,i和 i + 1 , i + 1 , i + 1 i+1,i+1,i+1 i+1,i+1,i+1三元组,这种决策不会影响最大值
CF1312E Array Shrinking
区间dp,
d
p
i
,
j
dp_{i,j}
dpi,j表示区间
[
i
,
j
]
[i,j]
[i,j]内合并后最少有几个数,
a
i
,
j
a_{i,j}
ai,j表示区间内合并成一个数后的值
枚举中间决策点时只有当左右两区间都为一个数且相等时,才能进行+1操作
其余正常合并即可
CF1025D Recovering BST
已知二叉排序树如果转换成区间dp可以直接枚举区间然后枚举中间点(即根节点),这是比较常规的思路,但是此题的特殊性在于:
O
(
n
3
)
(n^3)
(n3) 时间复杂度足够,但因为我们要记录一下某个区间
[
i
,
j
]
[i,j]
[i,j]应该以谁为根节点,才能更好转移,所以空间也要开到
n
3
n^3
n3,同样不够
我们考虑此题的描述问题的性质,首先题目要求的是树上相邻两点的gcd,这两点必定是父亲儿子关系,那么我们研究某个区间子树
[
i
,
j
]
[i,j]
[i,j]时,当这个区间向外扩展时,它的父亲节点一定是i-1或j+1,那么我们在处理出
[
i
,
j
]
[i,j]
[i,j]是否合法时,就可以预先判断一下当前区间根节点k能否与i-1和j+1连边,这样我们第三维只用开2空间即可
CF13C
CF713C
每次操作
+
1
−
1
+1 -1
+1−1,变成不下降序列,某一最优解的最终序列上的数一定是原序列中出现的数
CF713C,要变成递增序列,转换一下将
a
i
=
a
i
−
i
a_i=a_i-i
ai=ai−i
CF1198D
一个矩形可以分成两个矩形,然后就会变成一个相同的子问题,直接递归dfs记忆化即可
CF1316E
首先考虑当观众,排序选前几最大的。
现在有比赛,发现如果前几大不选去做观众,就一定要去比赛,否则不会最优
换种方式说:现在选了一些人去比赛,肯定会选择剩下前几大做观众
那么先按做观众的贡献排序,对于一个人有三种决策,不选,选去比赛,选去做观众。
总结下来:枚举到
i
i
i
如果
i
−
p
o
p
_
c
o
u
n
t
(
m
a
s
k
)
<
k
i-pop\_count(mask)<k
i−pop_count(mask)<k,选去做观众或去比赛
如果
i
−
p
o
p
_
c
o
u
n
t
(
m
a
s
k
)
>
=
k
i-pop\_count(mask)>=k
i−pop_count(mask)>=k就不会再有去做观众这种决策,所以不选或选去比赛
CF1699D
f
i
f_i
fi表示以由
a
i
a_i
ai结尾,最终形成的相同数字串长度最大值
很容易想到肯定要枚举
j
j
j转移到
i
i
i
f
i
=
m
a
x
(
f
j
+
1
)
f_i=max(f_j+1)
fi=max(fj+1)
然后我们想一下转移的条件是什么, a i = = a j a_i==a_j ai==aj且 [ i + 1 , j − 1 ] [i+1,j-1] [i+1,j−1]中的数字个数为偶数且能删除。继续想:删除的条件会是什么呢?手玩一下发现,只要最大的数字不超过数字总数的一半即可
CF383D
首先考虑固定左端点的情况,然后背包扫一遍选右端点累加就可以了
然后我们想要加入其它左端点,只要枚举的时候更新一下
f
i
,
+
−
a
[
i
]
f_{i,+-a[i]}
fi,+−a[i]就行了
CF152E
首先考虑最优解的形态,会发现其实是关键点连通成一颗树
先考虑最好想的做法,关键点很少,可以状压。但是状压完要怎么转移?
如果只由哪些点连通了去转移,会发现不好求最优,我们考虑添加状态,连通两个连通块时,我们的转移点是什么,这样只要将两个连通块分别与转移点连一条最短路就行了。但是我们发现还是不好转移,不妨换种转移的思路。
在我们每次将两个连通块相连时,我们还要更新该连通块到每个点的最小花费(类似于跑一边最短路),也就是说我们的花费每次转移最多只会加一,把多次形成的复杂转移分解出来,最后记录一下转移决策就可以了
CF675E
假设
f
i
f_i
fi表示
i
i
i到
[
i
+
1
,
n
]
[i+1,n]
[i+1,n]最小花费和,发现转移不好搞,考虑逆序转移
那么有一个转移点的贪心,当我在
i
i
i时,我有一个花费1跳的区间范围
[
i
+
1
,
r
i
]
[i+1,r_i]
[i+1,ri],首先这个范围我们只要1就能到达,然后我们后续其它点
[
r
i
+
1
,
n
]
[r_i+1,n]
[ri+1,n]的花费,一定是从
[
i
+
1
,
r
i
]
[i+1,r_i]
[i+1,ri]中的某个点转移过来的。
发现
j
∈
[
i
+
1
,
r
i
]
j \in[i+1,r_i]
j∈[i+1,ri]中最大的
r
j
r_j
rj就是最佳转移点。
证明:跳到
j
j
j后下一步的选择范围明显会更广
然后就可以转移了
CF 1481E
假设让一种数字不移动,其它数字一定能平均花费1使得序列合法,这样只要找到出现次数最多的数字即可
但111222,可以分为两段,然后选取出现次数最多的数字,花费为0
那么考虑dp求最大不移动数字数,逆序转移
f
i
=
m
a
x
(
f
i
+
1
,
c
n
t
a
i
)
f_i=max(f_{i+1},cnt_{a_i})
fi=max(fi+1,cntai)
合并:
f
i
=
m
a
x
(
f
i
,
f
r
a
i
+
1
+
c
n
t
a
i
)
f_i=max(f_i,f_{r_{a_i+1}}+cnt_{a_i})
fi=max(fi,frai+1+cntai)
The 2019 ICPC Asia Nanjing Regional Contest I
因为
a
i
<
=
50
a_i<=50
ai<=50很小,所以一旦当前能量大于等于50时,直接上组合数统计方案。然后组成50的状态是很少的,记忆化搜索。
先将数组中的0去掉,最后单独计算,然后排序,dfs,数组
c
n
t
i
cnt_i
cnti作为状态(不管怎么选,当数组
c
n
t
i
cnt_i
cnti相同时,剩余贡献都一样),哈希优化状态,然后开一个unordered_map来记录值
CF 1575L
P6564
f
i
f_i
fi 表示以
i
i
i 结尾,最长为多少。那么我们考虑什么样的
j
j
j 可以转移到
i
i
i,列出式子发现是个二维偏序,那么排序+树状数组或者排序+CDQ都可以