UOJ Σ* Round #1 题解
写在前面
由于第二题原本的题目描述并不对应解法,且原本的题目表述是更为困难的问题,第二题题面应该进行修改。然而,发现这一点时比赛时间已经接近结束(我在复核题解证明的时候发现的错误),因此我们不得不遗憾地宣布,由于这一问题,我们现在对第二题的题目描述进行修改,并且本场比赛将不会计分(unrated)。
最开始的第二题游戏规则是这样的,没有现在这样的多轮操作:
首先艾莉芬在棋盘上放置一些带颜色的积木。然后蔡德仁可以对棋盘进行任意次操作,然后交给艾莉芬再进行任意次操作,之后棋盘会进行左、下两次操作把所有积木收拢到左下角。
这是我没有做足够的验证和数学证明中的失误造成的错误,再次向各位参赛选手深表歉意。
彩色括号
- 题意、题面、题解:liu_cheng_ao
- 标程、数据:WeLikeStudying
思路
问题研究对象是满足条件的括号序列:整体合法且删掉每种单个颜色之后都合法,那么考虑怎么判断一个括号序列是否满足条件。
括号序列合法当且仅当:
- 左右括号个数相等
- 所有前缀和非负(将
()
分别视为 )
分别考虑:
- 由于整体左右括号个数相等且删掉红色之后左右括号个数还是相等,作差可以得到红色左右括号个数相等。同理每个颜色都如此。
- 考虑某个位置
的前缀和,设红绿蓝的前缀和分别是 ,那么 。可以发现当 同时成立时,全部相加可得 。所以 这个条件不用单独考虑。
所以总的条件是:
- 每种颜色左右括号个数都相等。
- 删掉每种颜色得到的前缀和分别非负。
这是判断条件。现在我们再考虑如何用最少的修改次数让一个括号序列合法,发现:
)
改(
一定是前若干个)
,(
改)
一定是最后若干个(
。可以调整证明。- 所以可以贪心:如果某种括号多,那么先改那种括号到数量平衡。然后从外往里每次将第一个
)
和最后一个(
一起修改,直到前缀和全部非负为止。这就是最小修改次数。
加上颜色限制后,每种颜色内部还是符合这个条件。所以我们不妨先把每种颜色都改到数量平衡,设这样改完后的整个序列是
然后设
考虑合法性对
对于前缀 )
个数,而 (
个数。另外设
可以列出不等式组:
将
其中
所以整个问题就是在这个约束下最小化
三种颜色的约束是在这个图的形状上求离原点曼哈顿距离最近的点:
算法
按照思路所说,先做让每种颜色左右括号数量平衡必要的修改得到
三种颜色的情况下,可以看成三个形如
或者你可以直接把它当成实数线性规划手算答案公式然后向上取整,在本题三种颜色的特殊情况下这是对的。
时间复杂度:
扩展
根据思路,显然我们可以做更多颜色的情况。设颜色数为
本题考虑出四种颜色的情况,但鉴于选手的体验并没有这么做。
部分分
如果你没有发现不等式组,可以用双指针和区间数据结构算出每两种颜色的约束。(没有不等式组不容易发现约束只有三段,但至少可以发现是二维偏序上的阶梯型)
然后仍然可以
时间复杂度:
如果你只发现了一部分性质,可以做更前面的部分分。
积木对战
- 题意、题面、题解、锅:liu_cheng_ao
- 标程、数据:Yanami
思路
问题给了一个上下左右的操作方式,我们要研究它。不妨用
观察问题并手玩一些例子,发现:
- 显然相邻的
会抵消,相邻的 也会抵消。抵消之后操作序列中 和 只能交替出现。奇数位置和偶数位置是两个子序列,分别只有 和 。 - 另外,形如
或者 这种片段,第二个 没有效果(一个 之后只要没有 所有积木都是靠最右的),可以消掉。同理, 都如此。 - 所以可以推出消到最简的操作序列按下标
恰好分别是 四种操作。实际上,长的操作序列只能是不断重复“顺时针转圈” 或者“逆时针转圈” 。
那么一个操作序列的基本效果是
加上颜色之后,转一圈总的效果就是在积木之间进行一个置换,对于固定的角上堆积的形状来说,置换是确定的,设为
(到这里我们可以解决 [ROI 2024] 2026 (Day 1) 这一问题。)
我们会发现,只要积木已经堆到了角落,那么后续它怎么操作都能逆回去。所以堆积在左下角的方案数是置换
然后我们要考虑不到一个周期的情况。要保证无论蔡德仁如何操作艾莉芬都能操作,所以一个必要条件是初始局面
可以得到以下条件:
引理 1 一个矩阵
- 充分性:通过操作的定义证明原来的结果等于删去这行/列后子矩阵的操作结果加上这行/列的结果,然后归纳。
- 必要性:假如不存在,那么每行每列都既有空也有积木,则
后第一列必定全满, 后第一行必定全空,左上角这一格矛盾,必然形状不同。
然而,在此基础上,满足这个条件的局面在
反例:
010 100 100 234 [LD]200 [DL]300 050 534 254
计算出
一开始的做法给这一点做了伪证,并且没有做足够的暴力验证。
做法认为:
一个初始局面是符合题目要求的,当且仅当:
- 它可以通过不断删去当前全空或全满的行/列删到空。(形状条件)
- 它在
之后得到的颜色分布可以被最终状态的置换生成。(颜色条件)
所以认为原问题答案等于形状的方案数乘以颜色的方案数。具体来说,形状的方案数等于
因此,实际上题目应该这样安排游戏规则:艾莉芬先操作一次,再让蔡德仁染色。但这样仍然需要给答案增加一些分类讨论和常数系数,因此被迫修改成现在的题面。对于现在的题意来说,这个做法是对的。
然而,原问题的困难性也没有得到证明,并且可以发现在
算法
(对于没改之前的题面是假的)
形状的方案数:先算出
颜色的方案数:算出最终状态上
两者相乘即为答案。
时间复杂度:
程序校验
题意、题面:OldDriverTree, liu_cheng_ao
题解、标程、数据:OldDriverTree
算法 1
每次暴力模拟,总时间复杂度
期望得分 5 分。
算法 1.5
考虑对暴力算法进行极限卡常,但是本题操作本质串行,无法使用指令集优化。
这里介绍一种对指令集的通用攻击手段:计算连续访问数组的 L1 缓存缺失量。
强制在线会导致遍历数组时发生大量的 L1 缓存缺失。
为了卡常到极限,利用取模生效次数很少的性质,可以将
评测机的 CPU 的 L1 缓存行大小为 32B 的数据缓存和 32B 的指令缓存,每个核心的 L1 缓存总大小为 32KB 的数据缓存和 32KB 的指令缓存。L1 缓存命中时需要约
如果暴力算法可以通过,则 1s 处理遍历数组时发生的 L1 缓存缺失次数为
不过对于数据范围较小的测试点,有优化后的暴力算法获得了非平凡的分数。
期望得分 5~15 分。
算法 2
针对
考虑每次使用数据结构高效找到接下来第一次该数会发生取模的位置,等价于给定
这个问题可以倒着从后往前维护持久化值域线段树,维护每个值最近被覆盖的时刻,每次加入一个区间的时候做区间染色。
于是对每个位置
总时间复杂度
期望得分 15 分。
算法 3
如果所有询问的
先考虑简化的,没有
倒着维护每个后缀的函数复合结果,
初始是
特别需要注意的是,对于持久化 treap 来说,区间复制
这样可以
再考虑如果有
针对
期望得分 35 分。
算法 4
回顾算法 2,持久化值域线段树功能受限无法进行区间平移和复制操作,考虑将其换成持久化平衡树来支持更强的操作。
于是倒着从后往前维护持久化平衡树,维护每个点最近被覆盖的时刻,每次的操作有区间染色,区间复制,分裂合并等,都是持久化平衡树支持的操作。
对每次查询,使用预处理好的数据结构每次
总时间复杂度
期望得分 55~75 分。
算法 5
我们发现对于
每次查询需要按顺序找到
这个方法可以顶层分块,底层分块,将线段树变成多叉线段树来极大地减少常数。
顶层分块:可以发现线段树的根结点的没有用的,只有
底层分块:可以发现线段树的叶子结点是没有用的,如果建立的持久化平衡树,则每次查询是
多叉线段树:可以发现线段树加上底层分块和顶层分块后二叉就不优了,于是将线段树改为多叉的。
利用右儿子:可以发现线段树结点可以直接从其右儿子处继承过来持久化平衡树,然后只需要将左儿子的部分插入即可。
利用左侧查询的优势:可以发现询问的部分如果是某个线段树结点的后缀,则可以不用暴力,而是用持久化平衡树的一次查询代替。
总时间复杂度
这个算法没有利用取模的特性,所以不优,在其他没有好的性质的题中是已知的最优做法。
利用以上技巧极限卡常后,期望得分推测为 55~85 分。
算法 6
我们考虑使用 “全局平衡” 的思想,类似于树链剖分套线段树的那种问题,每次查询如果需要在
我们在这个问题上,尝试将一开始的持久化平衡树的做法进行拓展,使得其可以进行区间查询,并且将第二,四种暴力做法的思想结合进去,即利用每次只会发生
我们在持久化平衡树上维护每条边的边权,有两种颜色的边,分别是红色和黑色。红色的边的含义是下方结点是某次取模导致的区间复制复制产生的,黑色的边的含义是正常持久化平衡树的边。
每个叶子结点到根结点的路径上最多只有
具体实现的时候,我们需要对每条红色的边记录下这条边是序列上哪个位置产生的,持久化平衡树的重新平衡(如旋转)仅限于对黑色的边,对红色的边是不做重新平衡的。平衡操作可以看做是产生新的边,以及将原本两条新的边压缩为一条边。由于我们是通过红色的边来找到每次取模的位置的,所以重新平衡的时候对红色的边做平衡操作会使得找取模位置的时候少找了一些,只能对黑色的边做操作。
每次查询
其实可以进一步解释本题做法,我们需要维护一个 DAG 结构,使得从任何点出发,该 DAG 深度是
本做法对于其他持久化平衡树做法有显著优势,因为其他做法需要多次查询持久化平衡树,本做法只需要一次查询,虽然本做法的平衡树由于“全局平衡”的性质所以常数比正常平衡树大。
总时间复杂度
期望得分 100 分。