Educational Codeforces Round 119 (Rated for Div. 2) EFG 题解

Solution

赛时切了 ABCDEG,不会 F。

E

考虑使用若干个集合 S i S_i Si 维护各个数出现的位置,那么两个操作分别可以被抽象为:

  • 在一个集合中加入一个数。
  • 将集合 S x S_x Sx 合并到集合 S y S_y Sy 处。

对于操作一,直接插入即可。
对于操作二,考虑启发式合并:

  • ∣ S x ∣ < ∣ S y ∣ |S_x|<|S_y| Sx<Sy,则枚举 v ∈ S x v \in S_x vSx 并将 v v v 插入到 S y S_y Sy 中,最后将 S x S_x Sx 清空。
  • ∣ S x ∣ > ∣ S y ∣ |S_x|>|S_y| Sx>Sy,则枚举 v ∈ S y v \in S_y vSy 并将 v v v 插入到 S x S_x Sx 中,接着将 S x S_x Sx S y S_y Sy 调换位置,最后将 S x S_x Sx 清空。

我们需要一个 O ( 1 ) O(1) O(1) 插入, O ( 1 ) O(1) O(1) 交换的数据结构,不难想到 STL 中的 vector。其交换的底层实现是直接交换指针,所以插入和交换也是 O ( 1 ) O(1) O(1) 的;相信,写过长链剖分优化 dp \text{dp} dp 的 Oier 都知道。

于是,总复杂度与启发式合并同阶,为 O ( n log ⁡ 2 n ) O(n \log^2 n) O(nlog2n)AC链接

因此啊,这题做法与《五彩斑斓的世界》毫无关联,不要像我一样,数据结构学傻了。

F

似乎是比赛中最难的一道题,至少本蒟蒻 VP 时及赛后看题解之前着实不太会做。

Key Observation

序列 t t t 为二分序列当且仅当其中不存在长度为 3 3 3 的下降子序列。

算法一

做过 NOI 2018 冒泡排序的人应该都很容易想到算法一吧。

考虑 dp \text{dp} dp

f i , M , m f_{i,M,m} fi,M,m 表示,钦定了序列的前 i i i 位,目前的最大值 M M M,目前没有作为前缀最大值最大值 m m m 时,这个状态能够达到 ( 0 / 1 ) (0/1) (0/1)

考虑转移。假设这一位填上了 k ( k = ± p i ) k(k=±p_i) k(k=±pi)

  • k < m k<m k<m,则不能填 k k k,不可转移。
  • m ≤ k ≤ M m \le k \le M mkM,则有转移 f i , M , m → f i , M , k f_{i,M,m} \to f_{i,M,k} fi,M,mfi,M,k
  • M < k M<k M<k,则有转移 f i , M , m → f i , k , m f_{i,M,m} \to f_{i,k,m} fi,M,mfi,k,m

边界: f 0 , − ∞ , − ∞ = 1 f_{0,-∞,-∞}=1 f0,,=1

记录转移来源即可构造出一组解。然而,时间复杂度为 O ( ∑ n 3 ) O(\sum n^3) O(n3),无法接受。

下面的算法就是我没想到的了,感觉还是对今后的做题有一定启发意义的。

算法二

考虑对状态设计进行转化——令 g i , j g_{i,j} gi,j 表示,看了 [ 1 , i ] [1,i] [1,i],最大值为 j j j,没有作为前缀最大值的数的最大值最小可以为多少(有些绕口,建议多读几遍)。

为什么可以进行转化呢?这是因为,若 k 1 > k 2 k_1>k_2 k1>k2,纵使 f i , j , k 1 = f i , j , k 2 = 1 f_{i,j,k_1}=f_{i,j,k_2}=1 fi,j,k1=fi,j,k2=1 f i , j , k 1 f_{i,j,k_1} fi,j,k1 依然是比 f i , j , k 2 f_{i,j,k_2} fi,j,k2 差的。我们完全可以摒弃其中较差的那一个。

考虑 g g g 如何转移。假设这一位填上了 k ( k = ± p i ) k(k=±p_i) k(k=±pi)

  • k < g i , j k<g_{i,j} k<gi,j,则无法转移。
  • g i , j ≤ k ≤ j g_{i,j} \le k \le j gi,jkj,则有转移 g i + 1 , j : = min ⁡ ( g i + 1 , j , k ) g_{i+1,j}:=\min(g_{i+1,j},k) gi+1,j:=min(gi+1,j,k)
  • j < k j<k j<k,则有转移 g i , j → g i + 1 , k g_{i,j} \to g_{i+1,k} gi,jgi+1,k

边界: g 0 , − ∞ = 1 g_{0,-∞}=1 g0,=1

时间复杂度 O ( n 2 ) O(n^2) O(n2)无法通过本题

算法三

与算法二同构,唯一的区别在于 g i , j g_{i,j} gi,j j j j g i , j g_{i,j} gi,j 的实际意义调换了一下。

算法四

仔细观察我的代码,你会发现——转移的过程中,要么新的 j j j 等于 k k k,要么更新的值等于 k k k

因此啊,状态 g i , j g_{i,j} gi,j 合法,当且仅当 j = k j=k j=k g i , j = k g_{i,j}=k gi,j=k

综上所述,我们定义状态 h i , p , q h_{i,p,q} hi,p,q 表示,目前看了 [ 1 , i ] [1,i] [1,i],目前最大值还是非前缀最大值的最大值为 k k k p = 0 / 1 p=0/1 p=0/1),以及目前 k k k p i p_i pi 还是 − p i -p_i pi q = 0 / 1 q=0/1 q=0/1),其中 h i , p , q h_{i,p,q} hi,p,q 存储的是另一个的最大值。这样一来,只要结合算法二与算法三的转移,总复杂度就是线性的了。

总复杂度 O ( n ) O(n) O(n),完美解决本题。代码懒得写

Summary

本题是一道非常不错的 dp \text{dp} dp 题,有一定难度。

首先,我们应该凭借直觉猜出 Key Observation,然后凭借已有的做题经验顺理成章地想出 O ( n 3 ) O(n^3) O(n3) 的算法一。关键在于优化

算法一中的 dp \text{dp} dp 存储的只有 0 , 1 0,1 0,1 而没有具体的值,并且同对 ( i , j ) (i,j) (i,j) 对应的 k k k 之间有鲜明的强弱关系,这引导我们将第三维缩掉作为存储的值。于是得到 O ( n 2 ) O(n^2) O(n2) 做法。

接着,我们需要察觉到——对于一个二分序列,从左往右扫描的过程中,一个数要么作为非前缀最大值中的最大值,要么作为前缀最大值,否则不合法。因此,得到结论——状态合法当且仅当其存储的值或其第二维度就是 k k k。然后就能得到线性的正解了。

观察整个思路流程,其实就是秉承了降维的思想,先后使用分明的强弱关系以及题目的特别性质将后两维缩掉。因此,我们要细致观察强弱关系是否鲜明以及特别性质,以便于最终将状态优化数到可以接受的量。

G

板子题。

f s f_s fs 表示,集合 s s s 中的字符串的 f f f 值。
g s g_s gs 表示,作为 s s s 中所有字符串的公共子序列的字符串数量。

通过容斥,容易得到

f s = ∑ t ∈ s ( − 1 ) ∣ t ∣ − 1 g t f_s=\sum_{t \in s} (-1)^{|t|-1} g_t fs=ts(1)t1gt

显然,只要求出了 g g g,则可以通过一遍 FWT O ( 2 n n ) O(2^n n) O(2nn) 地求得 f f f;所以关键在于如何求出 g g g

注意到各个字符串中字符都是有序的,所以不难发现——若字符串 T T T S s 1 , S s 2 , ⋯   , S s k S_{s_1},S_{s_2},\cdots,S_{s_k} Ss1,Ss2,,Ssk,当且仅当 T T T 是有序的,且 ∀ c ∈ [ 1 , 26 ] \forall c \in [1,26] c[1,26] T T T c c c 出现的次数不超过 S s 1 , S s 2 , ⋯   , S s k S_{s_1},S_{s_2},\cdots,S_{s_k} Ss1,Ss2,,Ssk 中的任何一个字符串中 c c c 的数量。因此,通过乘法原理很容易得出, g s g_s gs 就是 s s s 中各个字符串中 1 1 1 出现的次数的最小值 × \times × 2 2 2 出现次数的最小值 ⋯ \cdots × \times × 26 26 26 出现次数的最小值。通过递推可以做到 O ( 2 n × 26 ) O(2^n \times 26) O(2n×26)

从而,总复杂度为 O ( ( n + 26 ) 2 n ) O((n+26)2^n) O((n+26)2n),可以通过本题。AC链接

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
"educational codeforces round 103 (rated for div. 2)"是一个Codeforces平台上的教育性比赛,专为2级选手设计评级。以下是有关该比赛的回答。 "educational codeforces round 103 (rated for div. 2)"是一场Codeforces平台上的教育性比赛。Codeforces是一个为程序员提供竞赛和评级的在线平台。这场比赛是专为2级选手设计的,这意味着它适合那些在算法数据结构方面已经积累了一定经验的选手参与。 与其他Codeforces比赛一样,这场比赛将由多个问题组成,选手需要根据给定的问题描述和测试用例,编写程序来解决这些问题。比赛的时限通常有两到三个小时,选手需要在规定的时间内提交他们的解答。他们的程序将在Codeforces的在线评测系统上运行,并根据程序的正确性和效率进行评分。 该比赛被称为"educational",意味着比赛的目的是教育性的,而不是针对专业的竞争性。这种教育性比赛为选手提供了一个学习和提高他们编程技能的机会。即使选手没有在比赛中获得很高的排名,他们也可以从其他选手的解决方案中学习,并通过参与讨论获得更多的知识。 参加"educational codeforces round 103 (rated for div. 2)"对于2级选手来说是很有意义的。他们可以通过解决难度适中的问题来测试和巩固他们的算法和编程技巧。另外,这种比赛对于提高解决问题能力,锻炼思维和提高团队合作能力也是非常有帮助的。 总的来说,"educational codeforces round 103 (rated for div. 2)"是一场为2级选手设计的教育性比赛,旨在提高他们的编程技能和算法能力。参与这样的比赛可以为选手提供学习和进步的机会,同时也促进了编程社区的交流与合作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值