刷题总结2

· · 个人记录

同步于cnblogs

T1 AT_joisc2007_buildi ビルの飾り付け (Building)

简化题意

最长上升子序列模板

分析

O(n^2)做法

考虑DP

  1. 定义状态:dp_i表示以i结尾的最长上升子序列长度
  2. 确定答案:\max{dp_i}
  3. 状态转移:对于每个a_i: (1)当a_i>a_j(j<i)从以第j个数结尾的地方再接一个数,即dp_j+1 (2)自己单独成一个子序列
  4. 边界条件:dp_i=1(每个数都能单独成一个子序列)

    O(n\log n)做法

    考虑贪心(往死里贪) 所以对于最大上升子序列,结尾元素越小,越有利于后面接上其他的数,也就可能变得更长 所以创建一个数组c,用来存贮现在的最长上升子序列中的元素 对于每个a_i,可以在c数组中找到一个第一个比他大的数,那么这个数就能替换掉c数组中的那个数,而dp_i的答案就是找到的数的下标,因为前面都是比他小的数,自然的,他也可以接在这些数后面 但是这样可能还是要扫一遍c数组,但我们能发现,c数组永远是单调递增的!所以使用二分大法,时间复杂度O(n\log n) P.S.:c一定要初始化为无穷大,因为数要越小越好

    Code

    link1 link2

    T2 AT_abc281_d [ABC281D] Max Multiple

    分析

  5. 定义状态:dp_{i,j,p}表示前i个数,选了j个,余数为p时的最大和
  6. 答案:dp_{n,k,0}(dp_{n,k,0}\geq0),否则为-1
  7. 方程: (1)不选这个数:dp_{i-1,j,p} (2)选这个数:dp_{i-1,j-1,(p-a_i)\mod d }+a_i
  8. 边界:dp_i=-\infdp_{0,0,0}=0

    Code

    link

T3 AT_abc369_d [ABC369D] Bonus EXP

题意简化

n只怪物,每只怪物有一个数值a_i,对于每只怪物,你有两种选择:

  1. 放走他,获得0经验
  2. 击败他,获得a_i经验,特别的,如果这只怪兽是你击败的偶数只怪物,你还可以额外获得a_i经验 求最后你能获得多少经验

    分析

  3. 定义状态:dp_{i,0/1}表示前i个怪物,选了奇数/偶数个怪物的最大经验
  4. 答案\max(dp_{n,0},dp_{n,1})
  5. 状态转移方程: (1)选第i个怪物,且为奇数个:\max(dp_{i-1,0},dp{i-1,1}+a_i) (2)选第i个怪物:\max(dp_{i-1,1},dp_{i-1,0}+2\times a_i)
  6. 边界:由于a可能有负数,所以dp设为负无穷

    Code

    link

还有两题有时间补上