cunzai_zsy0531

关注我

CF1398F Controversial Rounds 题解

Post time: 2021-10-29 18:22:46

题面


贡献一个官方题解做法的详细解释。

首先注意到一个贪心的思路,从前往后如果能够使某一段长度 \(=x\) 就一定会使其 \(= x\)\(\geq x\)

考虑设一个函数 \(f(pos,x)=npos\) 表示当限制长度为 \(x\) 时,从 \(pos\) 这个位置开始往后,第一个能够出现连续 \(x\)01 的位置为 \(npos-1\)。如果能够 \(O(1)\) 求出这个函数的值,那么每一次都令 \(pos=npos\) 继续往下做,由于每一次至少会加 \(x\),所以这样的复杂度就是 \(O(n\ln n)\)

如何求这个函数的值呢?再考虑设两个数组 \(nxt0_i,nxt1_i\) 分别表示从 \(i\) 开始的最长 0 段和 1 段的长度。这个可以倒序递推求得。再设 \(p0_x\) 存下所有的下标 \(i\) 满足 \(i\) 开始往后有连续的 \(x\)0,且 \(i=1\)(开头)或者 \(s_{i-1}=1\)\(p1_x\) 同理。

考虑对于某个 \(x\),从 \(1\) 开始走,设当前走到 \(now\),如果 \(nxt0_{now}\geq x\),则 \(npos=now+x\);否则就找到 \(p0_x\)\(\geq now\) 的最小的位置(使用双指针实现),设其为 \(tmp\),则 \(npos=tmp+x\)。对 \(nxt1\)\(p1\) 的处理同理,这样就能做到最开始的 \(O(1)\) 求得 \(f(pos,x)\),所以总复杂度是 \(O(n\ln n)\)

本人代码过于冗长,就不贴 code 了,CF官方题解上的代码写的比我要好。

posted @ 2022-04-21 22:23  cunzai_zsy0531  阅读(18)  评论(0编辑  收藏  举报