Loading

总结 9.7

有两道 qoj 的还没看。

AGC022E Median Replace

题意:一个长度为 \(n\)\(01\) 串,有一些位置为通配符。若存在一种方案,每次消去三个连续的字符,然后在相同位置插入它们的中位数,共操作 \(\frac {n-1} 2\) 次后,剩下的数是 \(1\),那么这是一个完美的 \(01\) 串(保证 \(n\) 是奇数)。求有多少个完美的 \(01\) 串,模 \(10^9+7\)\(1\le n\le3\times10^5\)


手玩一下,不难发现几个点:

  • \(000\) 肯定最赚。

  • 存在 \(0\) 时,不可能消 \(111\)

  • 消除有 \(0\)\(1\) 的三个字符,相当于删掉一组 \(01\)

进一步贪心模拟,设当前我们保留了 \(x\)\(0\)\(y\)\(1\)

  • 遇到一个 \(0\):令 \(y\leftarrow y+1\),当 \(y=3\) 时,令 \(y\) 变为 \(1\)

  • 遇到一个 \(1\):如果 \(y>0\),中间的 \(y\)\(0\) 肯定要消去,不妨直接令这个 \(1\) 与其中一个 \(0\) 一起删掉,即 \(y\leftarrow y-1\);否则,\(x\leftarrow x+1\)

最终合法的条件即为 \(x\ge y\)

不难发现,\(y\) 始终满足 \(y\le 2\)

于是令 \(x'=\min(x,2)\),设 \(f[i,j,k]\) 表示考虑到第 \(i\) 位,此时 \(x'=j,k=y\) 时的方案数。

答案:\(f[n,0,0]+f[n,1,0]+f[n,2,0]+f[n,1,1]+f[n,2,1]+f[n,2,2]\)

UOJ748 【UNR #6】机器人表演

题意:有一个长为 \(n\)\(01\) 串,你需要计算 \(t\) 次操作后能得到多少不同的 \(01\) 串。一次操作的定义为:在串中选两个位置插入一对 \(01\) 使得 \(0\)\(1\) 前。\(1\le n,t\le300\)


不难得到一种 \(\text{DP}\):设 \(f[i,j,k]\) 表示考虑了最终串的前 \(i\) 位,与给出的串匹配了 \(j\) 位,剩下位置的字符的权值和(字符 \(0\) 的权值为 \(1\),字符 \(1\) 的权值为 \(-1\))为 \(k\) 的方案数。

转移:

  • 加入一个 \(0\):如果与给出串的 \(j+1\) 位相同,那么 \(f[i+1,j+1,k]\leftarrow f[i+1,j+1,k]+f[i,j,k]\);否则 \(f[i+1,j,k+1]\leftarrow f[i+1,j,k+1]+f[i,j,k]\)

  • 加入一个 \(1\):如果与给出串的 \(j+1\) 位相同,那么 \(f[i+1,j+1,k]\leftarrow f[i+1,j+1,k]+f[i,j,k]\);否则 \(f[i+1,j,k-1]\leftarrow f[i+1,j,k-1]+f[i,j,k](k>0)\)

我们在此过程中的“匹配”是贪心匹配,不一定考虑到了所有的方案。比如给出的串为 \(000\),操作 \(1\) 次后有合法的最终串 \(00100\),但我们可能会先把前两位贪心匹配了,此时 \(j=2,k=0\),我们在 \(\text{DP}\) 中就没有计算到第 \(3\) 位填 \(1\) 的情况(因为此时 \(k=0\))。

正确的做法应该是在原来贪心地匹配上加点料,如果当前 \(k=0\),我们考虑撤回一些匹配位,用这些位置凑出权值和为 \(1\) 让给 \(k\)。设 \(to[j]\) 表示撤销到哪个位置后可以凑出权值和为 \(1\),那么 \(f[i,j,0]\rightarrow f[i+1,to[j],0]\)

答案:\(f[n+2t,n,0]\)

CF gym 103860I

题意:给出一个 \(01\) 序列,你可以把序列的某一段翻转,可以翻转 \(k\) 次,求最终序列的 \(\text{LIS}\) 最大是多少。


考虑如果没有翻转操作,枚举一个位置 \(i\),设 \(s_0(x)\) 表示 \(1...x\)\(0\) 的个数,\(s_1(x)\) 表示 \(x+1...n\)\(1\) 的个数,那么答案为 \(\max\limits_i\{s_0(i)+s_1(i+1)\}\)

有两个量看着不顺眼,设 \(s(x)\) 表示 \(0\) 的权值为 \(1\)\(1\) 的权值为 \(-1\)\(1...x\) 的权值和,那么答案为 \(s_1(n)+\max\limits_i\{s(i)\}\)

考虑翻转怎么做。手玩一下,发现其实就是选择一个前缀,再选 \(k\) 个互不相交且不与前缀相交的段,每一段的权值和总和的最大值。

考虑先给第一个位置的权值加个 \(\inf\),问题变成了选择 \(k+1\) 个互不相交的段。

这是一个经典问题,用线段树维护模拟费用流即可。

CF1416E Split

题意:给出 \(n,a_{1...n}\),把每个 \(a_i\) 分裂成两个正整数,他们的和为 \(a_i\)。分裂后形成了一个有 \(2n\) 个数的序列,求这个序列的相同连续段数的最小值。\(1\le n\le5\times 10^5\)

考虑 \(\text{DP}\)

“相同连续段数的最小值”相当于求“相邻相同数字对数的最大值”,设 \(f[i,j]\) 表示考虑了 \(a_{1...i}\) 的分裂,\(a_i\) 分裂出来的后一个数为 \(j\) 时的相邻相同数字对数的最大值。

\[f[i,j]=\max_k\{f[i-1,k]+[k+j=a_i]\}+[2j=a_i] \]

这个 \(\text{DP}\) 非常特殊,单个 \(a_i\) 的贡献最大为 \(2\),而且单个 \(f[i-1,k]\) 对所有的 \(f[i,j]\) 都有贡献。

\(g=\max_k\{f[i-1,k]\}\),那么

\[f[i,j]=\max(g,f[i,a_i-j]+1)+[2j=a_i] \]

后面那个 \([2j=a_i]\) 属于最后的单点修改,我们可以先不管。考虑前面的,发现当 \(f[i,a_i-j]=g\)\(f[i,j]\) 才等于 \(g+1\),否则等于 \(g\)

这启示我们存下一个最优决策集合。设 \(S\) 表示 \(k\in S,f[i-1,k]=g\)。转移时先把 \(S\)\(\ge a_i\) 的数删掉,然后把所有 \(x\in S\) 变成 \(a_i-x\)。如果 \(a_i\) 为偶数,并且 \(\frac {a_i} 2\in S\) 时,此时 \(f[i,\frac{a_i}2]\) 就会变成最大的数,令 \(S\) 中只剩一个数 \(\frac{a_i}2\),然后更新 \(g\);若 \(\frac {a_i}2\not \in S\),则把 \(\frac{a_i}2\) 加入 \(S\)

不难发现,\(S\) 中的数一定是形如“一个区间 + 一些单点”,单点数量是 \(O(n)\) 的,容易维护。对于把 \(S\) 中的操作 \(x\in S,x\leftarrow a_i-x\),我们维护一个乘法标记 \(mul\) 和一个加法标记 \(add\),令 \(add\leftarrow add\times (-1),mul\leftarrow mul\times(-1),add\leftarrow add+a_i\) 即可。集合可以用 \(\text{set}\)

时间复杂度 \(O(n\log n)\)

CF1500F Cupboards Jumps

题意:给出 \(n\)\(w_{1...n-2}\),你需要构造 \(a_{1...n}\),满足 \(\forall i(1\le i\le n-2),w_i=\max(a_i,a_{i+1},a_{i+2})-\min(a_i,a_{i+1},a_{i+2})\),给出构造方案,或确定无解。\(3\le n\le 10^6\)


有个重要的套路:设 \(b_i=a_{i+1}-a_i(1\le i\le n-1)\),那么 \(w_i=max(|b_i|,|b_{i+1}|,|b_i+b_{i+1}|)\)。进一步的,若 \(b_i,b_{i+1}\) 同号,\(w_i=|b_i+b_{i+1}|=|b_i|+|b_{i+1}|\),否则 \(w_i=max(|b_i|,|b_{i+1}|)\)。设 \(c_i=|b_i|\),那么 \(w_i\) 等于 \(c_i+c_{i+1}\)\(\max(c_i,c_{i+1})\)。我们只需要构造出 \(c_{1...n-1}\),然后推出 \(b_{1...n-1}\)\(a_{1...n}\)

不难想到 \(\text{DP}\),设 \(f[i,j]=0/1\) 表示构造了 \(a_{1...i}\),并且 \(a_i=j\),是否存在这样的方案。

考虑转移:

  • \(f[i,j]\rightarrow f[i+1,w_i]\)

  • \(f[i,w_i]\rightarrow f[i+1,0...w_i]\)

  • \(f[i,j]\rightarrow f[i+1,w_i-j]\)

用人话说:

  • 先排除掉 \(f[i,w_i+1...\inf]\)

  • 如果 \(f[i,0...w_i]\) 中有 \(1\),那么 \(f[i+1,w_i]=1\)

  • 如果 \(f[i,w_i]=1\),那么 \(f[i+1,0...w_i]\) 全为 \(1\)

  • 对于一个位置 \(j\),如果 \(f[i,j]=1\),那么令 \(f[i+1,w_i-j]=1\)

\(i\) 看做常量,考虑维护一个集合 \(S\),表示 \(j\in S,\space f[i,j]=1\)。在 \(i\rightarrow i+1\) 的过程中,\(S\) 有如下变动:

  • \(S\)\(>a_i\) 的数删掉。如果删完后集合为空,那么无解。

  • 如果 \(a_i\)\(S\) 中,把 \(0...a_i-1\) 全部加入集合 \(S\);否则先把集合中所有的 \(j\) 变成 \(a_i-j\),然后把 \(a_i\) 加入 \(S\)

不难发现,\(S\) 中的数总是“一个区间+一些单点”,单点数量是 \(O(n)\) 的,维护方法和上题类似。特别的,每次加入 \(a_i\) 总是 \(S\) 中最大的,可以用 \(\text{deque}\) 来代替 \(\text{set}\)

然后构造方案直接反推,时间复杂度 \(O(n)\)

posted @ 2023-09-07 09:06  Lgx_Q  阅读(28)  评论(0编辑  收藏  举报