加载中...

CF edu 174 (A~E)

A

  1. \(b[i]=1\) -> \(a[i-1]=a[i]=a[i+1]\)
  2. \(b[i]=0\) -> \(a[i-1]!=a[i]\space or \space a[i+1]!=a[i]\)

显然让某个 \(b[i]=1\) 不成立很难。考虑让某个 \(b[i]=0\) 不成立。则当 \(b\) 中出现连续的 \(1 \space 0 \space 1\) 时才会发生这种情况,判断即可。

code

B

首先钦定好最终变成哪个颜色,则其他颜色一定需要操作,且每种颜色的操作是独立的,故最小化总操作次数即最小化每一种颜色的操作次数。

考虑让某一种颜色操作次数最小,要注意到:

  1. 相同颜色的不同的联通块一定可以同时操作
  2. 每个联通块的最大操作数为2(手玩一会儿就能发现肯定是这样)

因此找某种颜色的最大联通块 \(size\),则这种颜色的操作次数为 \(min(size,2)\)。所有颜色加和即为总数,减去其中某一个需要最大操作数的颜色即可。

code

C

相当于找原序列中 \(1 \space (若干个2) \space 3\) 的子序列数量。

由于要找的序列中只有一个 \(1\)\(3\),且分别一定在最左侧与最右侧。因此可以考虑枚举 \(1\),计算当前的 \(1\) 作为子序列左端点时,右侧部分的方案数。

\(a[i]=1\),计算 \(a[i]\) 为子序列左端点时的子序列个数:

找到右边的所有 \(3\) ,设某个 \(j>i且a[j]=3\),设 \((i,j)\) 之间有 \(num\)\(2\), 则这个 \(a[j]\) 的贡献为:\(2^{num}-1\)

设某个 \(a[j]=3\),且 \((i,j)\) 内有 \(num_{j}\)\(2\),则 \(a[i]=1\) 的贡献可表示为:

\[\sum_{j=i+1,a[j]=3}^{n}(2^{num_{j}}-1) \]

对这个式子没办法直接算前缀和,考虑拆一下式子:设一共有 \(k\)\(j>i且a[j]=3\),则上式可改为:

\[(\sum_{j=i+1,a[j]=3}^{n}2^{num_{j}}) - k \]

其中左边的每一个加项均为 \(2\) 的幂次,只与 \(2\) 在区间内的个数相关。故可以利用前缀和 \(pre2\) 来维护某个区间 \(2\) 出现的个数,则左式就可以利用前缀和来计算(具体见代码),而计算 \(k\) 则直接维护 \(suf3\) 即可。

code

子序列计数 \(dp\) 解法:

code2

D

\(eazy\) 的贪心。

显然原字符串的前后缀匹配上的字符一定不会选,因此可以直接取中间的子段,这个子段一定满足前缀与后缀的字符不匹配,因此删除段一定是某个前缀或后缀。

设删除两端后的子段长度为 \(n\),则先考虑删除长度 \(<=n/2\) 的情况:可以从 \(i=n/2\) 处开始,并令 \(i\) 逐渐减小,看第一个从里向外不相匹配的字符位置 \(i\)——则看前缀 \([1,i]\) 与后缀 \([n-i+1,n]\) 每种字符是否一一对应即可。

若无解,则只能考虑删除长度 \(>n/2\) 的情况:此时删除段内会有自身相匹配的情况。可以让删除段与非删除段的字符先一一匹配,若有多出来的字符对,则考虑放在自身相匹配的位置。看 所有自身匹配的位置数量 是否可以容纳 所有多出来的字符对 即可,贪心 \(check\) 一下就行。具体细节见代码。

code

E

\(hard\) 的构造 + 贪心

首先要注意到,相邻的相同字符之间一定是要切分出来的。将这些位置提前找出来,剩下的所有子串的形式就只可能有 \(4\) 种情况:

  1. \(ABAB...A\)
  2. \(BABA...B\)
  3. \(ABAB...B\)
  4. \(BABA...A\)

其中1和2可能会有单独的 \(A\)\(B\),这只能作用于 \(a\)\(b\)。而对于某个 \(AB\)\(BA\),它被拆分时一定会同时增加一个 \(A\) 和一个 \(B\),即会同时作用于 \(a\)\(b\)。因此除了单独的 \(A\)\(B\),对于其他形式的子串,以下三个变量的增加和减少可以任意互相转换(后面会证明,现在只是猜测会有这个结论。至于怎么能猜出来,我也不知道qwq...):

  1. \(min(a,b)\)
  2. \(ab\)
  3. \(ba\)

首先对长度为奇数的两种情况1和2做下观察:以1为例。其中 \(A\) 的数量一定比 \(B\) 多一个,显然其中至少要有一个 \(A\) 被单独切分出来。设该串为 \(ABABABA\),则钦定其中的某个 \(A\) 被删,会有四种不同的情况出现:

  1. \((A)\space BA\space BA\space BA\)
  2. \(AB\space (A)\space BA\space BA\)
  3. \(AB\space AB\space (A)\space BA\)
  4. \(AB\space AB\space AB\space (A)\)

可以发现,剩下子串中的 \(AB\)\(BA\) 的数量是可以以总数不变的情况下任意分布的。又因为任意 \(AB\)\(BA\) 均可以同时拆出一个 \(A\) 与 一个 \(B\),所以可得出: \(ab\)\(ba\)\(min(a,b)\) 可以自由分配地减去一个固定的值(这里是3)。情况2类似于情况1。

可以发现上面 "\(ab\)\(ba\)\(min(a,b)\)自由分配地减去一个固定的值" 这个性质是非常好的,因为我们不用再具体关注某一项是否够用,而只需要看它们的和够不够即可,这个是很容易的。因此拆分时,我们要尽可能地多构造出 "\(ab\)\(ba\)\(min(a,b)\)自由分配地减去一个固定的值" 这种情况。

而对于情况3和4,它们的长度是偶数,以情况3为例,能够发现若想构造出上面的好性质,就必须拆出一个开头的 \(A\) 或者一个结尾的 \(B\),转化为情况1或情况2。这两种拆分的最终结果均是得到了单独的一个 \(A\) 和 单独的一个 \(B\),剩下的子串可以 对 \(ab\)\(ba\)\(min(a,b)\) 自由分配减去一个固定的值。或者是只将整个串划分成若干 \(AB\),不再有自由分配。能够证明对于情况3和4,只有这两种分割情况是最优的,证明我也不会。

那么情况3,4中上面所说的两种分割方式应该怎样抉择呢? \(ABABAB\) 形式的串按后者划分时只会作用于 \(ab\),贪心地想:\(ab\) 足够时,能按后者划分就尽量按后者划分(也是不会证明),当不够时再按前者划分。那么还有一个问题:对于不同长度的形式为 \(ABAB...AB\) 的串,应该先对哪些用后者划分呢?可以发现,先对短的用后者划分会更好,因为可以保证剩下的 \(ABABAB\) 形式的串更少,而之前的证明中说过,对于每一个偶数长度形式的串,必须先划分出单独的一个 \(A\) 和 单独的一个 \(B\),才能再做自由分配。而串的数量越少,这种“必须”就越少,划分的自由度也就越高,显然更优,所以从小到大排序后贪心即可。

将所有“必须”的情况先做好,在合法的情况下,\(check\) 剩下的“自由分配总数”是否 \(<=\) 剩下的 \(ab + ba + min(a,b)\)即可。具体细节见代码。

code

posted @ 2025-02-19 13:05  jxs123  阅读(47)  评论(0)    收藏  举报