杂题选做【S-C1】

【S-C1】是啥意思??

01. CF1858E2 Rollbacks (Hard Version)

维护一个初始为空的序列 a,支持以下操作:

  • x:在序列末端插入 x
  • k:在序列末端删除 k 个数(k 不超过当前序列长度);
  • ?:查询序列中不同的数字个数;
  • !:撤回前一个 +/- 操作。

q 次操作,强制在线,1q,x106,询问操作不超过 105

解法

垃圾 *2600。

经典地,我们用 set 维护所有数字的出现的所有位置,更新时只需要查询其首位即可。

这样我们可以轻松实现 + 操作。

为了实现 - 操作,我们引入序列 A,使得序列 A 的前 l 位恰好为序列 al 为序列 a 此时的长度)。这样一来,我们更新时直接将 l 更改为 lk 即可。

这样做同样是为了方便进行 ! 操作。因为我们实际上保留了 1lmax 的所有信息,足以进行回溯。

对于 ! 操作,我们使用 stack 存储所有操作,并尝试逆向地进行还原,具体情况与上面的 +/- 操作思路一致。

特别地,对于 + 操作,我们需要存储原来的 Al 而不是 x。这是容易理解的。

至于答案的更新,我们在所有元素第一次出现的位置标记为 1,这个是已经维护过的。

那么 ? 操作只需要输出该数组在 [1,l] 上的区间和即可。

至此,我们需要一个可以支持单点修改、查询区间和的数据结构。拉一个树状数组即可。

时间复杂度 O(qlogq)

https://codeforces.com/contest/1858/submission/219045104

考虑优化,逐个解决瓶颈:

  • 树状数组:可以用前缀和替代。容易发现是可行的;
  • 维护各个元素出现的位置:我们发现改变一个元素第一次出现的位置,必然伴随着一个当前已知位置该元素的更新或该元素的彻底删除。据此可以只用一个数组 pos 代替上述题解中提出的 set 进行维护。

据此,我们得到时间复杂度 O(q) 的做法。代码从略。

02. CF1804F Approximate Diameter

给定一个 n 个点 m 条边的初始无向图,有 q 次更新,每次更新向图中添加一条边。设 d(Gi) 代表加入 i 条边后的图中两点之间的最大距离,你需要输出 q+1 个整数 a0,a1,,aq,满足 d(Gi)2ai2d(Gi)

n,m,q105,图连通。

解法

牛逼 *2700。

考虑一个性质,以某个点为端点的最长路径长度 s 满足

d(Gi)2sd(Gi)

证明从略。

但是发现这个比要求的更紧。考虑怎么利用这个 2d(Gi)

显然地,我们考虑二分某个答案什么时候失效,此时我们将该答案除以 2 即可。这是可行的,因为这个一眼单调。

二分枚举端点再套枚举答案即可,时间复杂度 O(nlog2n)

https://codeforces.com/contest/1804/submission/219393324

注意我们钦点的 dijkstra 算法别写丑,不然无法通过。

03. CF992E Nastya and King-Shamans

给定序列 a,维护两种操作:

  • 单点将 aix
  • 查询 i=1n[(j=1i1aj)=ai]

1n,q2×1050a109

解法

还不错的 *2500。

考虑一个性质:答案最多为 logn

证明从略。我们考虑直接拉线段树维护然后暴力遍历即可找到答案。

时间复杂度 O(qlog2n)

https://codeforces.com/contest/992/submission/219414380

04. CF825G Tree Queries

一棵树有 n 个节点,初始均为白色,有两种操作:

  • x:把节点 x 染为黑色;
  • x:查询 x 到树上任意一个黑色节点的简单路径上的编号最小的节点的编号。

保证第一个操作为染色操作,强制在线。3n1061q106

解法

小清新 *2500!

首先,显然地,为了方便维护,我们以第一次染色的节点 t 为根 dfs 一遍以求出所有节点到 t 的简单路径上的编号最小的节点的编号,即数组 a

然后画个图可以理解:

  • 对于染色操作,将目前维护的一个答案 ansmin(ans,ax),可以证明这是正确的;
  • 对于询问操作,我们输出 min(ans,ax) 即可。

这是因为,我们的对于不同 t 的子树间的路径 uv,有 utv 即为其简单路径。而对于子树内的路径,可以用 ut,vt 覆盖整个路径。

至此问题得到 O(n) 解决。

https://codeforces.com/contest/825/submission/219512635

05. CF1503D Flip the Cards

你有 n 张牌,第 i 张牌的正面有整数 ai,背面有整数 bi。所有 12n 的整数都出现过正好一次。

我们认为这 n 张牌是好的当且仅当 ai 升序,bi 降序。

可以进行下面的操作:

  • 交换 ai,bi
  • 随意重排这 n 张牌。

求如果要使这 n 张牌变成好的最少需要翻几次牌,或报告无解。

解法

牛逼 *2600。可惜放了 log 过。

我们考虑到,若存在一个 i 使得 ai,bin,则必然无解。

于是考虑将所有牌变成 ai<bi 的情况,则必然有 ain,bi>n。于是设 f(ai)=bi

下面研究 f(i)。发现当且仅当 f(1n) 可以被分为两个单调递减子序列使有解。

minj=1i{aj}>maxj=i+1n{aj} 处断点分段处理最小值即可。

时间复杂度 O(n),远超 log 且更巧妙。

同时注意到没必要管顺序。

https://codeforces.com/contest/1503/submission/219536981

06. CF1646F Playing Around the Table

n 个人坐成一个圈,每个人手上有 n 张麻将,麻将上是 1 萬到 n 萬,每次可以让每个人同时掏出一张麻将给下一个人,构造一组方案使得第 i 个人能够做成「i 萬一色」。

要求,操作次数不超过 n2n1n100

解法

萌萌 *2900。

我们考虑到,为了方便处理,设计一个过渡态「一气通贯」使所有情况达到统一。

可以证明,初态 「一气通贯」i 萬一色」这一变换中,第一步的操作次数不超过 n(n1)/2,第二步的操作次数为 n(n1)/2

下面,我们证明第一个。发现离「一气通贯」最远的状态是每个人均有一个「j 萬一色」,证毕。

https://codeforces.com/contest/1646/submission/219623330

感觉还是比较难想的,所以场上才仅 3 人通过。

07. CF802H Fake News (medium)

构造字符串 s,p,使字符串 s 的为 p 的子串恰有 n (1n106) 个。

解法

萌萌 *2200!感觉思路比较牛逼。

我首先想到了 CF1368B Codeforces Subsequences,不同的是,这道题是至少 n 个。

一个朴素的想法是,对于恰好有 k 个子串的情况 (s,p),我们可以实现 k2k

具体地,任取一个新字符 c,令 s=sccp=pc 即可(这里直接用字符串拼接表示了)。

但是我们不能实现 kk+1。这是很困难的。否则我们可以直接二进制拆分 n 解决。

考虑另一个思路,假设对于恰好有 k 个子串的情况 (s,p)s 可以被表示为 puu 也是一个字符串),任取一个新字符 c,那么我们可以实现

  • k2k+1:令 s=pcuccp=pc 即可;
  • k2k+2:令 s=pccuccp=pc 即可。

这之后我们均直接可以更新 u

于是我们递归地解决这个问题即可。考虑每次处理 x 时,先解决 x12 时的情况,再回溯解决。容易发现这是合理的。

边界是 x=1,2。这个也是平凡的,只需要使 p=a 即可。

这个是很对的,不考虑 string 类的复杂度是 O(logn)。由于 226>106,我们可以仅用小写字母解决本题。

https://codeforces.com/contest/802/submission/219735685

posted @   CSP_Sept  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示