ACM题解:MexSequences扭曲的线性dp
把过去和现在的笔记记录也搬了过来,也算是给以后留个念想吧,想想一开始打acm就是图一乐,后来发现这游戏还挺上头的,也算是度过了一段电竞生涯(xs)
早些时候的笔记写的好中二,连我自己看着都羞耻。
不过,就喜欢这种羞耻的感觉。
收录的题目大部分是个人认为质量不错的题目,以DP为主,非DP的题目都用※进行了标识。
当然,有些题解思路本身也是源自其他人的,不过除非特殊标注,否则都是用的自己的代码。
题目大意:
CF1613D Mex Sequences
题目大意,给一个数组a,长度范围在5e5内。定义一个性质MEX-correct:对于序列中的每一个数xi,都有abs(xi-MEX(x0,x1,…,xi))<=1,求数组a满足这个性质的子序列个数,取模998244353。
解:
一眼5e5,个数,取模,线性dp,然后不会了,开摆。
MEX的题也做过了,这题中很容易想到,对于一个满足Mc性质(简写了)的序列中的数xi,当时的MEX值要么等于xi+1要么等于xi-1,因为MEX不可能等于本身,如果MEX值只能等于xi-1时很好办,我们只要去从下往上线性dp把数量计算出来,使得序列最终包含0-xi的数(加上xi本身之后)就完了。而第二种情况实际上也很好算,我们只需要算序列包含0-(xi-1)的个数就行,因为它是个特例,为什么这么说呢?因为一旦出现了这种情况,MEX的值成为了xi-1,在这个序列的后面要是再想添加数,就只能添加这个数本身或者本身减二(最麻烦的地方),其他任何数都会出现错误,所以它没有后效,只要作为特例处理就行。
于是我们设计一个dp[i][j][2],表示最远涉及到第i个数的结尾j的Mc序列数量,后面的标记则是表示属于哪种情况,对于第一种情况实际上我们求的是一个不降子序列,第二种情况则是叠加。由于实际上我们不需要求最长的子序列,只要求数量,所以只要顺序遍历即可,第一维大可以不必,复杂度为O(n)。
状态转移:
dp[a[i]][1]+=dp[a[i]][1]+dp[a[i]-1][1],
dp[a[i]][2]+=dp[a[i]][1]+dp[a[i]][2],
dp[a[i]+2][2]+=dp[a[i]+2][2](这步很关键,千万不能少,而且注意是加在a[i]+2上而不是a[i],因为在这里第二个方程和第三个并不完全一样,第二个是从第一种情况转化成第二种情况,第三个则是一开始就在第二种情况,所以它是被当作以a[i]+2为结尾的序列看待的);这题还是蛮难的,从各种程度上来讲,细节也很多,需要很熟练这种计数方法,甚至最后还要卡你个memset,不愧1900之名好吧……
不过2000分以下的线性DP的极限也就到这了呢(笑代码(代码还挺简洁的……这里我之前写的代码中dp1和dp2对应题解中的dp[][1]和dp[][2]):
代码
1 |
|