Codeforces Round #773 (Div. 1) A~D 题解

比赛链接

A

开个 map,能选掉就选掉。

B

阴间构造

对于这种构造,我们肯定是要先找到一种基本操作,然后根据基本操作去构造方案。

不难发现无解的必要条件是存在数字出现了奇数次。下面我们通过构造方案证明其他情况下一定有解。

基本操作:翻转一段区间,即 abc cba

操作如下:

abcabcaa_abcabb_aabcabcc_ba[abcabc]cba

从前往后扫描序列,将相邻两个相同字符的位置配对,假设其中一对是 (i,j)

那么我们可以通过依次翻转 (i,j1)(i,j)j 移动到 i 之后且其他字符相对顺序不变。

举个例子:假设序列为 abca

操作如下:

abcaabcaa_aabcabb_aaabcabcc_baaabcabccbaacc_abcabccbaacbb_cabcabccbaacbaa_bcabcabccbaacbaaa_abc[abcabc][cbaacbaa][aa]bc

代码实现(可能?)需要一定的技巧性。

具体的,每做完一次操作就将已经操作过的数移到最前面,对剩余数重新计算匹配位置,顺便记录一下当前移动到的位置。

参考代码:

C

容易发现如果一个询问的答案是 YES,就相当于有一个区间只有这一个位置没有被覆盖成 0

经过转化后的题意:

  • 若操作为 0 l r 0,相当于将 [l,r] 全都覆盖成 0
  • 若操作为 0 l r 1,相当于加入一条线段 [l,r]
  • 若操作为 1 x,算出以 x1 为右端点的最长的一个为 0 的段的左端点 l1,和以 x+1 为右端点的最长的一个段为 0 的右端点 r1,相当于询问有没有一条线段 [l,r] 使得 l1lxxrr1

线段树二分之后离线差分变成三维偏序,CDQ 分治即可。

上面那句话也就图一乐。

考虑并查集 + set 启发式合并,每次覆盖就把 [l1,r] 的集合并起来,加入线段就直接在 r 所在的集合加入点 l,查询直接看在 x 所在集合有没有点在 [l1,x] 之间,l1 也可以并查集算。

注意 set 启发式合并的时候直接交换两个 set 即可。

D

核心:两个序列 {a}{b} 没有相同元素的判断方法:记一个计数器 cnt,对于每一个 b 的子集,如果它的元素个数是奇数,就将 cnt 加上它在 a 中的出现次数,否则就减去它在 a 中的出现次数。最后如果 cnt=1 说明 ab 至少有一个元素相同,否则它们就没有相同元素。

有这个结论之后对每一个子集哈希,双指针求答案即可。

posted @   csxsi  阅读(78)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示