AT3950 [AGC022E] Median Replace
约瑟夫用脑玩
2021-07-27 09:42:21
题解区令人迷惑的一道题,我来认真解释一下。
这是一篇偏理解的题解,如果你想理解而不是写代码的话可以来瞰瞰qwq。
先考虑对于无 “?” 的确定串考虑是否合法,首先我们要求最后剩的数是 1,那么我们就得消 0。
消 0 最有效的手段就是 000,我们从左往右维护一个栈表示前面剩余数的情况,那么我们希望看到的就是 0 堆在栈顶,从而消去 0。
考虑栈顶都是 0 时来了个 1,我们偏感性的理解一下:
- 如果只是虚晃一枪,后面继续给你丢 0,那么我们显然把 [x01]00... 变成 [x]00 不劣,更可能消 000。
- 如果是真的要给你很多 1,那么我们把 x[011]1.. 变成 x[1]1 也不劣,本来就会挨着往前消。
简单来说就是如果后面来 1,我们正常来说就会把这个 01 给消掉,如果后面来 0,这个 01 阻断了前后 0 的相连,我们也会把它消掉。
那么以上就是栈顶堆 0 的情况:
- 如果有 000 直接消成 0,血赚,情况不变
- 如果有 01,消掉不亏,情况不变或把 0 消完
栈顶堆 1 的情况:
- 如果一直来 1,我们暂且不考虑需要几个 1,先堆着,情况不变。
- 如果来了 0,我们希望的就是 0 堆着消掉,我们也堆着,此时就转化为栈顶为 0 的情况。
发现按此策略,0上面不可能堆 1,1 上面可能堆 0。
那么有情况:空栈,全是 0,全是 1,1 上有 0。
但由于串为奇数,每次消掉 2 个,最后的栈也一定为奇数。
首先 0 至多 2 个,如果再多就会有 000 消掉,那么有三种情况:
1. 栈顶堆 0,下面无 1,即 1 个 0,不合法。
1. 栈顶堆 1,没有 0,即 11111...奇数个 1,合法
1. 栈顶堆 0,下面有 1,考虑 0 和 1 的数量:
- 11100 此时合法
那么我们发现下面堆的 1 只用留 3 个就可以把 2 都消掉,如果 1 比 3 多一定合法。
- 1110 为奇数,不存在
- 1100 不存在
- 110 合法
- 100 不合法
- 10 不存在
如果手动编号转移可能把人都转崩,发现用 0,1 的个数来代表状态是唯一确定的!
$\left(x,y\right)$ 代表栈中 $x$ 个 0,$y$ 个 1。
以下仅列举串长为奇数的情况,偶数同理,画个表格(横 $y$):
$\begin{array}{|c|c|c|c|c|}(x,y)&0&1&2&>2\\0&\text{空栈}&\text{合法}&\text{不存在}&\text{合法}\\1&\text{不合法}&\text{不存在}&\text{合法}&\text{合法}\\2&\text{不存在}&\text{不合法}&\text{不存在}&\text{合法}\end{array}$
如果丧心病狂,手动转移,把不存在的状态全部压掉应该可以做到 $5\sim6$ 种状态。
完全不压直接转移就是 12 种状态,压了一半是 9 种状态。
我说停、停,还能压一半?然而事实就是如此,许多题解都这么搞:把 $y=3$ 的那层直接压到 $y=2$ 的那层转移,仍然使用 0,1 的个数自动转移。
这样做常数肯定减小,但就特别的搞人理解,关键是说的不清楚!
就算有 “?” 自动化转移也很好实现,代码就不放了。