CTS2024

Day1 T1 水镜

WC 赛时做法

考虑对于相邻的两个位置 ii+1,他们之间的连通性可以用一个 2×2 的矩阵描述,即 i 对应的两个位置是否和 i+1 对应的位置可以连接。

发现这个 2×2 的矩阵只会变化一次,且变化的时刻就是 hi+hi+12 的时刻,那么总共变化的时刻也只有 O(n) 次。

我们在初始的时候和每一次修改一个位置的时候,可以使用线段树上二分向左右拓展,看能够拓展到哪里,每一次会得到 O(1) 个极长的区间。

把这所有 O(n) 的区间包含的区间数统计出来即可。时间复杂度 O(nlogn)

题解做法

pi=max(hi,2Lhi),发现如果段区间 [l,r] 合法,说明 p 的结构形如 pl>pl1>>pk1?pk<pr1<pr 的单谷结构。

发现存在这个结构就等价于不存在 pi1pipi+1,考虑对于 hi1,hi,hi+1 之间的大小关系讨论,可以得到 L 不能属于的区间:

hi1<hi hi1=hi hi1>hi
hi<hi+1 [hi+hi+12,+) [hi+max(hi1+hi+1)2,+)
hi=hi+1 (,hi+hi12] (,+) [hi+hi12,+)
hi>hi+1 (,hi+min(hi1,hi+1)2] (,hi+hi+12]

每一种情况都对应着值域的一个前缀或者后缀,那么一个区间 [l,r] 不能取的 L 的集合是一个 (,L][R,+) 的结构,可以直接维护 LR

我们要统计所有满足条件的区间的数量,考虑双指针,但是发现双指针不好维护删除。所以考虑使用 baka's trick 可以做不删除扫描线,时间复杂度 O(n)

Day1 T2 线段树

发现线段树等价于一组三角剖分,而一个区间 [l,r) 的值已知就是在 lr 之间连接一条边。如果区间 [L,R) 可以被表示,等价于 LR 之间联通。

由此我们可以根据连通性设计 DP。

fi,j 被线段树 i 节点(对应区间 [l,r)),其中和 l 联通的编号最大的点为 j 的方案数;gi 为线段树 i 节点,只考虑下面的边,lr 联通的方案数

通过枚举 [l,r) 是否连接,可以得到如下 DP:

  • 2glsgrsgi
  • glsfrs,jgi,glsfrs,jfi,j
  • fls,jgrsgi,fls,jgrsfi,j
  • fls,jfrs,kgi,fls,jfrs,kfi,j

但是在第四种转移中 (j,k] 这一段不和外界联通,这也就意味着题目中要求联通的所有区间都需要满足和 (j,k] 要么包含,要么不交。

考虑使用异或哈希来检验,将下标在 [L+1,R] 的所有数异或上一个随机值 val,如果 jk 处的权值 Vj=Vk,我们才能够合并。

由于需要将 V 相同的 DP 值合并,所以可以使用线段树合并来维护,时间复杂度 O(nlogV)

Day1 T3 众生之门

通过打表发现,在 n 较大,且他的结构不是菊花的时候,答案基本都是 01,而我们可以证明答案的奇偶性,也就可以大胆猜测,答案就是 0 或者 1

所以考虑特判掉这两种情况,然后其他的情况直接随机交换检验。

考虑正确性,我们可以认为答案在 0O(n) 中随机分布,那么我们期望检验 O(n) 个就可以得到一个 0 或者 1 的结果了。

Day2 T1 多方计算

考虑一个比较直接的做法:在第一次传输的时候,第 0 个人将最低位传给第 1 个人,第一个人将这一位加在自己的数上。第二次传输的时候,第 0 个人传第二位,第 1 个人传最低位。

这样最终得到的数会是一个 m+logn 位的数,由于最后一个人收到有 n 个时刻的延时,所以需要的时刻数为 n+m+logn

发现在前面的时刻,后面很多的人都没有操作,所以我们可以让后面的人在这个空闲的时候也处理一些运算,比如将后面的一部分的最后几位提前加上。

原本第 i 个人在第 r 轮要传递信息是第 ri1 位,如果 ri1<0,我们就然他传递第 ri1+m+logn 位,发现这样我们第一轮传递的数的位数变成了 m+loglogn,只需要 n+m+loglogn,大概是 n+m+4 次传递即可。

发现距离满分差 1。既然我们可以加一轮,那么也可以加两轮,所以通过调参之后再加一轮,变成三轮加法即可。

Day2 T2 投票游戏

我们需要想一个方法快速比较两个人谁先被票出去。发现如果有一个人被票出,那么所有人的票数都不会增加,那么如果我们记录每一个人被票出的时候他的票数 fi,那么我们就可以确定那个人先被票了。

发现一个人的状态之和他的所有儿子有关,假设我们确定了当前点 u 的所有儿子的票数 fi。将其从大到小排序,就是儿子被票出的顺序。记第 1i 个儿子的 b 值之和为 sumi,那么这个人被票出的时刻就是找到最小的 j,使得的 au+vsonubvsumj1>fj,那么 i 最终的票数就是 au+vsonubvsumj1,信息等价于找到第一个 au+vsonubb>fj+sumj1 的位置。使用平衡树维护所有儿子的顺序,同时维护 min{fj+sumj1} 就可以二分找到该位置。

这样做时间复杂度是 O(nlogn+qDlogn) 的,其中 D 为树的深度。瓶颈在修改,考虑使用树链剖分优化。

那么我们只用平衡树维护轻儿子,将重儿子 bs 单独拿出来讨论:我们将 au+vsonubv 扔进平衡树中二分,记得到的答案为 ans。如果 fbs<ans 说明重儿子不会影响到该节点被票出时的票数;否则,说明 bs 必然在 u 之前票出,票数也就会是 au+vsonubvbbs 的答案。

发现当前节点的票数关于重儿子的答案,是一个分两段的常函数,可以直接维护。

发现这样每一次修改只会变化 O(logn) 个平衡树,这样复杂度就是 O(nlog2n) 的。

Day2 T3 字符串游戏

将字符串反转,记 occ(l,r)S[l,r]S[1,r] 中的出现次数。记 fi 在字符串 S[1,i] 的答案,我们容易得到 DP:fr=max1lr(occ(l,r)fl)

对于 l1<l2,有 occ(l1,r)occ(l2,r),则如果 fl1fl2,那么 l1 处转移必然不优于 l2,这也就意味着,可能转移的决策点可以用一个单调栈维护,每一次压入 fi,将所有 fj>fi 弹出。

但是单调栈的大小仍然可能是 O(n) 量级的,没有对复杂度有实质上的优化。

考虑再发现一点性质。

对于 fp<fi 我们假设 i 的决策点为 q<p,不难发现,fpocc(q+1,p)fqocc(q+1,i)fq=fi,这与 fp<fi 矛盾,说明我们从单调栈的栈顶转移到 fi,如果当前栈顶 pfp<fi,那么后面的转移都不需要考虑了;否则意味着 fpfip 需要从单调栈中弹出。

这样转移的次数就被减少到了 O(n) 次,加上计算 occ(l,r) 需要后缀树上倍增定位位置,最终复杂度为 O(nlogn)

posted @   Xun_Xiaoyao  阅读(131)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
历史上的今天:
2023-08-08 后缀平衡树
/* 鼠标点击求赞文字特效 */
点击右上角即可分享
微信分享提示