Codeforces Round 947 (Div. 1 + Div. 2)

A

模拟。

B

最小的 \(a\) 肯定作为 \(i\)。对于不被 \(i\) 整除的,最小的那个作为 \(j\),判断是否合法即可。

C

二分答案。容易发现合法即存在两个 \(1\) 的距离 \(\le 2\)。

D

对于后手,当他走到一个红色点之后,接下来就没有任何限制了。所以先求出相遇点(可能不在点上,无伤大雅)。然后求以这个点为根的最长链即可。

E

一条路径必然存在两个端点,用 set 维护这两个端点,即叶子集合。

判断 \(u,v\) 是否合法,直接维护哈希值,判断其是否等于树上对应链的哈希值。

复杂度 \(O(n\log n)\)。

F

注意到是对于任意一个 \(T\) 都成立,肯定不能一个一个判。考虑把 \(T\) 按照最高位分成两组,除去这个最高位后它们就是相同的。

分讨:

  • 若 \(S\) 的最高位是 \(0\),那么相当于 \(\forall t\le 2^{n-1}-1,|S\cap T|\in V_{t}\) 且 \(|S\cap T|\in V_{t+2^{n-1}-1}\),那其实就是 \(V_{t}\) 和 \(V_{t+2^{n-1}}\) 取与。
  • 另外一种情况就是 \(V_{t}\) 和 \(V_{t+2^{n-1}}>>1\) 取与。

DFS 做到 \(O(n2^{n})\)。

G

首先假设没有 *,直接判断即可。

假设两个串都有 *,那么发现一个必要条件是两串的一段前缀需要匹配,两串的一段后缀需要匹配。不难得出这个就是充要的。因为中间的剩余部分已经满足两边均存在 *,两边的 * 都可以带一些数删去,然后又会变成一个两边都有 * 的情况,所以一定合法。

剩下的情况就是只有一边有 *,这些 * 把原来的串分成了 \(k\) 段,我们需要给每一段找到在另一个串中出现的位置,且这些串不能相交。那其实就是求出每个串在原串中的最小出现位置。暴力找匹配是 \(O(kn\log n)\) 的,但是注意我们并不需要把 \(1\sim n\) 拿出来找匹配,对于一个匹配位置 \(p\),只需要拿出来 \(1\sim p+k-1\) 就足矣。所以考虑倍增匹配,无论是否合法,每次都会删去同等级别的位置。因为一共只有 \(n\) 个位置,所以总的复杂度为 \(O(n\log n)\)。

H

首先肯定是把最大的字符 \(c\) 全部拿出来。发现最优情况下开头和结尾一定都是 \(c\),因为对于那些在第一个 \(c\) 前面的点,我们显然可以把他们放到第二个 \(c\) 的前面,这样一定更优。

那么整个串就形如 \(cs_{1}cs_{2}cs_{3}\dots cs_{k}c\)。假设 \(s_{i}\) 现在已经确定了,那么我们可以把 \(cs_{i}\) 看成一个整体,那么就递归成了一个子问题,即 \((cs_{1}),(cs_{2})\dots,(cs_{k}),c\) 这个串。不过此时比较并不是比较字典序,对于 \(cs_{i}\),后面需要加上一个 \(+\inf\),对于末尾 \(c\) 就再后面加上 \(-\inf\)。

于是现在我们只需要讨论每个 \(s_{i}\) 该怎么选能够使得答案最小。注意到 \(s_{i}\) 内部肯定递增,所以可以想到从小到大枚举每个字符 \(c'\),一个直接的想法是维护一个最大值集合 \(S\) 表示当前的最大值。每次把最小的 \(|S|\) 个字符添到 \(S\) 的每个最大值后面,然后会有一部分最大值被删去。反复维护这个过程。

直到出现剩下的字符不够了,另一个直接的想法是均摊地插入到这些最大值中间,使得长度最小,但是这样会有一些情况有问题。比如顺序会造成一些奇怪的影响。不过注意到此时每个 \(c\) 后面至多跟上一个字符,发现实际上 \(s_{i}\) 已经确定了,就是剩下的字符,如果不够的就是空的,于是可以递归到子问题 \((cs_{i})\)。

分析复杂度,设最开始 \(c\) 的个数有 \(a\) 个,不是 \(c\) 的个数有 \(b\) 个。

  • 如果是第一种情况,即 \(a\le b\),那么一次递归会使得 \(a>b'\)。
  • 如果是第二种情况,即 \(a>b\),那么一次递归会使得 \(a'=a-b\),不过注意到只要单个的 \(c\) 存在,那么它肯定是最大值,所以下一次我们并不需要重新计算 \(c\)。所以实际上我们可以使得 \(a'=a\bmod b\)。

总的递归轮数就是 \(O(\log n)\) 的,复杂度 \(O(n\log n)\)。

上述的递归过程访问了多次不是最大值的元素,这里有一个更优秀的做法。我们维护一个有序的序列 \(S\),最开始 \(S=\{-\inf,s_{1},s_{2},\dots,s_{n}\}\)(排序后的)。维护一个指针 \(pos\) 来表示当前为最大值的后缀。

从小到大扫 \(S\),每次把 \(S_{i}\) 加到 \(S_{pos}\) 的后面,然后 \(pos\) 加一。直到 \(pos=n+1\) 后,暴力往回跳寻找新的后缀。如果 \(S_{n}\) 的结尾是 \(-\inf\),则停止递归,输出 \(S_{n}\) 除去 \(-\inf\) 的部分。

为什么这样是对的呢?考虑每次添加,如果 \(S_{i}\) 结尾是 \(-\inf\),则表示这一轮递归开始了,第一个加到的位置就是末尾的 \(c\)。然后后面的数加到其他 \(c\),实际上就是上面的操作。

分析复杂度,注意到实际上 \(pos\) 每次往回跳后得到的新的 \(pos\) 一定不会比原来的小,所以复杂度是 \(O(n)\) 的。

Codeforces Round 947 (Div. 1 + Div. 2) A~H的更多相关文章

  1. Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship

    Problem   Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship Time Limit: 2000 mSec P ...

  2. Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems(动态规划+矩阵快速幂)

    Problem   Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems Time Limit: 3000 mSec P ...

  3. Educational Codeforces Round 43 (Rated for Div. 2)

    Educational Codeforces Round 43 (Rated for Div. 2) https://codeforces.com/contest/976 A #include< ...

  4. Educational Codeforces Round 35 (Rated for Div. 2)

    Educational Codeforces Round 35 (Rated for Div. 2) https://codeforces.com/contest/911 A 模拟 #include& ...

  5. Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings

    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings 题目连接: http://cod ...

  6. Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes

    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes 题目连接: http://code ...

  7. Educational Codeforces Round 63 (Rated for Div. 2) 题解

    Educational Codeforces Round 63 (Rated for Div. 2)题解 题目链接 A. Reverse a Substring 给出一个字符串,现在可以对这个字符串进 ...

  8. Educational Codeforces Round 39 (Rated for Div. 2) G

    Educational Codeforces Round 39 (Rated for Div. 2) G 题意: 给一个序列\(a_i(1 <= a_i <= 10^{9}),2 < ...

  9. Educational Codeforces Round 48 (Rated for Div. 2) CD题解

    Educational Codeforces Round 48 (Rated for Div. 2) C. Vasya And The Mushrooms 题目链接:https://codeforce ...

  10. Educational Codeforces Round 60 (Rated for Div. 2) 题解

    Educational Codeforces Round 60 (Rated for Div. 2) 题目链接:https://codeforces.com/contest/1117 A. Best ...

随机推荐

  1. Leetcode数组-二分法

    Leetcode数组-二分法 二分法学习地址 二分法 704. 二分查找 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 targe ...

  2. CSP-S2021 游记

    那天是惊蛰 满天花瓣 就像现在 我看清了无池里的那个人 前言 终于是开了 游记 的坑(期盼已久!) 虽然参加过 CSP-J2019 ,CSP-S2020 以及 NOIP2020 ,但是都没有写过游记( ...

  3. Redis数据存储和读写

    今天工作群里,有小伙伴问了一个问题,从Redis获取的数据,一会是0,一会是OK. 这引起了我们对Redis数据存储和读写的疑问. 以下是整理的一些技术研究内容. 在 Redis 中,所有的数据存储都 ...

  4. C++笔记(2)拷贝构造函数

    拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象. 如果在类中没有定义拷贝构造函数,编译器会自行定义一个.如果类带有指针变量,并有动态内存分配,则它必 ...

  5. MYSQL 移机重装步骤(windows11)

      MYSQL 移机重装步骤(windows11)   目的:已有电脑 A,D盘安装有mysql(安装方式为免安装) , 准备在另一台电脑B上,复制安装电脑A上的mysql(8.0.23版本) . 要 ...

  6. ansible搭建

    ansible配置步骤 1.创建用户 2.用户提权 3.用户免密 4.cp ansible配置文件 5.配置主机清单 6.修改ansible 用户路径下的配置文件 1.创建用户(都要做) [root@ ...

  7. Java常用的三个方法 `wait ` `notify` `notifyAll`

    常用的三个方法 wait notify notifyAll wait();方法使当前线程进入等待状态,直到另一个线程调用该对象的notify()或notifyAll()方法来唤醒它 notify(); ...

  8. 2024 Web 新特性 - 使用 Popover API 创建弹窗

    Popover API 为开发者提供了一种声明式的方式来创建各种类型的弹窗.目前已在所有三大浏览器引擎中可用,并正式成为 Baseline 2024 的一部分. 一直以来,我们在实现弹出式菜单.提示框 ...

  9. kettle从入门到精通 第三十五课 kettle 变量

    1.设置变量 a.可以通过转换中的"设置变量"步骤进行设置. b.手动通过kettle.properties文件或通过"编辑"菜单中的"设置环境变量& ...

  10. The solution of CF380C

    problem 希望这篇题解不要明年才审完. 标签:线段树 记录 \(Lsum_p\) 为这个区间有多少个 ( 不能匹配,\(Rsum_p\) 为这个区间有多少个 ) 不能匹配. 对于叶子结点如果是 ...