CF edu 174 (A~E)

A

  1. b[i]=1 -> a[i1]=a[i]=a[i+1]
  2. b[i]=0 -> a[i1]!=a[i] or a[i+1]!=a[i]

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

code

B

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

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

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

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

code

C

相当于找原序列中 1 (2) 3 的子序列数量。

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

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

找到右边的所有 3 ,设某个 j>ia[j]=3,设 (i,j) 之间有 num2, 则这个 a[j] 的贡献为:2num1

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

j=i+1,a[j]=3n(2numj1)

对这个式子没办法直接算前缀和,考虑拆一下式子:设一共有 kj>ia[j]=3,则上式可改为:

(j=i+1,a[j]=3n2numj)k

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

code

D

eazy 的贪心。

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

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

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

code

E

hard 的构造 + 贪心

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

  1. ABAB...A
  2. BABA...B
  3. ABAB...B
  4. BABA...A

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

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

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

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

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

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

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

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

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

code

posted @   jxs123  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示
主题色彩