刷题总结

同步于Luogu bolg然后发现洛谷渲染的还没cnbolgs好

题单

T1 AT_arc174_a A Multiply

题意简化

有一个长度为\(n\)的序列\(a\),你可以选择一个区间,让区间离的数全部\(\times c\),求\(a\)序列的最大值。

  • $ 1\ \le\ N\ \le\ 3\ \times\ 10^5 $
  • $ -10^6 \ \le\ C\ \le\ 10^6 $
  • $ -10^6 \ \le\ A_i\ \le\ 10^6 $

分析

观察数据范围,可发现\(c\)有正负之分,则想要让序列总长度最大,分类讨论:

  • \(c<0\),则需要使用最小的区间\(\times c\)
  • \(c>0\),则用最大的区间\(\times c\)
  • \(c=0\),则使用最小的区间\(\times c\)

所以要求两个东西:区间最大最小值
发现\(1\le n\le 10^5\),考虑DP

  1. 定义状态:\(dp_i \ or \ pd_i\):以\(i\)结尾的区间最大/最小值
  2. 答案:\(\max{dp_i}\ or \ \min{pd_i}\)
  3. 状态转移方程:由于区间是连续的,所以\(dp_i\)的状态只能由\(dp_{i-1}\)得到
    对于每个\(dp_i\)
    一.由\(dp_{i-1}+a_i\),得到新的子段和
    二.自己单独成一个子段
    得出\(dp_i=\max(dp_{i-1}+a_i,a_i)\)
    \(pd\)同理
  4. 边界条件:\(dp\)设极小值,\(pd\)设极大值

DP值求完了,接下来计算总序列和:

  • \((c>0)\)
    一.序列不变,因为可能序列全是负数,乘后还变小了
    二.减去区间最大值,再加上区间最大值\(\times c\)
  • \((c\le 0)\)
    一.序列不变,因为可能序列全是正数,乘后还变小了
    二.减去区间最小值,再加上区间最小值\(\times c\)

Code

link

T2 AT_dwango2017qual_b ニコニコレベル

题意简化

给你一个字符串,里面可能有数字或"?",你可以将问号替换成数字,求替换后这个字符串里面由"25"重复得到的字符串的最长长度
字符串长度小于等于1e5

分析

发现数据需使用\(\Theta(n) or \Theta(n\log_n)\)做法通过,考虑DP

  1. 状态: \(dp1_i\):第\(i\)个位置是\(2\)时的答案,\(dp2_i\):第\(i\)个位置是\(5\)时的答案
  2. 答案:因为答案必须以\(5\)结尾,所以得出答案为\(\max{dp2_i}\)
  3. 方程:对于每个"2"或"?":
    可以由上一个字符为\(5\)时的答案更新,并且不用考虑前一个数,可以直接单独成段
    对于每个"5"或"?":
    可以由上一个字符为\(2\)时的答案更新,但是要考虑前一个数,如果前一个数不是2,即\(dp_{i-1}=0\),则不能更新答案
  4. 边界:\(dp_i=0\)

Code

link

T3 AT_soundhound2018_summer_final_b Neutralize

题意简化

有一个序列\(a\),你可以进行任意次将\(k\)个连续的数变为\(0\),求最后数组的总和最大值

分析

由于有\(k\)的限制条件,显然不能使用一些暴力或暴力优化的方法通过,于是考虑DP

  1. 定义状态:\(dp_{i,1/0}\):表示前\(i\)个数,无\(k\)/有\(k\)的限制时的前\(i\)个数的答案

  2. 答案:\(\max(dp_{n,0},dp_{n,1})\)

  3. 状态转移方程:
    \(dp_{i,0}=\max(dp_{i-1,0},dp_{i-1,1})+a_i\)
    \(i-1-k+1\geq0\)
    \(dp_{i,1}=\max(dp_{i-k,0},dp_{i-1,1})\)

  4. 边界条件:\(dp[0][0]=dp[0][1]=0,dp_{i,0/1}=-\inf\)

Code

link

T4 AT_abc336_d Pyramid

题意

金字塔型序列:\([1,2,\dots,k-1,k,k-1,\dots,2,1]\)
给定一个长度为\(n\)的序列\(a\),可以进行重复性的两种操作:

  1. 将序列中某个数的大小减一
  2. 删除第一个或最后一个数

求能够形成的金字塔型序列的最大长度。

分析

比较常见的套路,洛谷也有类似的题:P1091 合唱队形
从左往右维护一个\(dp_i\):以\(i\)作为结尾的最长左金字塔序列的长度
从右往左维护一个\(pd_i\):以\(i\)作为结尾的最长右金字塔序列的长度
我们以\(dp_i\)为例,分别来观察一下

  • 1 1 2 3
  • 2 1 2 2
  • 3 3 1 2

按照题目中能把数变小和删除前后数字的操作,能推出当前的\(dp_i\)要从前面的\(dp_{i-1}\)和当前\(a_i\)较小的那个推过来:
$ dp_i=\min(dp_{i-1}+1,a_i)$

\(pd\)同理,最终枚举每个数作为金字塔尖,左边金字塔序列长度和右边金子塔序列长度中取小的那个能够形成的金字塔序列长度,然后维护一个最大值。

Code

link

posted @ 2024-11-27 21:41  KK_SpongeBob  阅读(33)  评论(0)    收藏  举报