关于一类DP题目的总结
1
题面:N个数字(有正有负)排成一排,选出连续一段使得和最大
N <= 1000000
S[i]表示前i个数的和
Ans = max{ S[i] –S[j] }, i>j>=0
Ans = max{ S[i] –min{S[j]} }, i>j>=0
边扫描边记录一个min值
时间复杂度O(N)
2
题面:N个数字(有正有负)排成一排,选出不重叠的连续两段使得和最大
N <= 1000000
正向扫描一遍,求出
F(x)=Max{ S[i] - S[j]}, x >= i > j >= 0
反向扫描一遍
G(x)=Max{ S[i] - S[j]}, i > j > x
枚举分割点
Ans=Max{ F(x) + G(x)}, 1 <= x <= N
时间复杂度O(N)
3
题面:N个数字(有正有负)排成一环,选出连续一段使得和最大
N <= 1000000
裸搞的话是O(N2)的吧,尽管我觉得裸搞都难想些
任取一处断环成链(并非复制数组)
若不跨越断点,按照1的方法做
若跨越断点,则未取部分对应最小和,按1求解
时间复杂度O(N)
4.
题面:N个数字(有正有负)排成一排,选出长度不超过L的连续一段使得和最大
N <= 1000000
S[i]表示前i个数的和
Ans = max{ S[i] – S[j]}, i – j <= L
= max{ S[i] – min{S[j]} }, i – j <= L
用堆或双端队列(单调队列)完成取每连续L个数中得最小值的操作
若j2<j1且S[j1]>S[j2]则j不可能最优
用队列维护
(j1<j2<j3……) (S[j1]<S[j2]<S[j3]……)
需要操作
----删除队首元素
----删除队尾不可能最优的元素
----队尾加入元素
时间复杂度O(N)
再回顾3如果我们将数组复制,再用此题单调队列方法维护亦可
5
题面:N个数字(正)排成一排,选出不重叠的长度不超过L的K段使得和最大
N, M, L <= 1000
F[i][j]表示第j段最后一个为第i个数字时的最大和
F[i][j] = Max{ f[i- L][j - 1]+s[i]-s[i - L],f[i - 1][j] }
还有一种类似的状态设计,不讲
时间复杂度O(N2)
6
题面:N个数字(正)排成一排,选出连续的长度不超过L的某些段(每段不得相邻)使得和最大
N <= 1000000,L <= 100000
单调队列
时间复杂度O(N)
7
题面:N个数字(有正有负)排成一环,选出不重叠的连续的K段使得和最大
N <= 100000, K <= 10
如3方法断环成链
F[i][j]表示前i个数取了j段的最大和
F[i][j] = Max{ F[k][j-1]+ S[i] - S[k] }, F[i-1][j] , k<i
= Max{Max{ F[k][j-1] - S[k] } + S[i], F[i-1][j] }, k<i
优化:G[i][j]=Max{ F[k][j-1] - S[k] }, k<i
时间复杂度O(N2)
8
题面:N个数字(有正有负)排成一排,选出连续一段使得和最大,且求方案数
N <= 1000000
此题是1的拓展
建立在理解1的基础上
1.在往后扫描时,若最大字段和一定时,cnt+1
2.在往后扫描时,若有同样的s[j]去更新min值,cmin+1
3.在往后扫描时,若最大字段和改变,cnt=1,cmin=1
最终方案数则为 cnt + cmin!
从学长资料里蒯了一些
也加上了最近KS的两道题
希望能对读者有所帮助
一有类似知识我将更新上来