JOISC 2021 记录

发布时间 2024-01-07 11:20:48作者: Xun_Xiaoyao

Day1 T1 Aerobatics

神秘的提交答案题。

Day1 T2 IOI 熱の感染拡大

我们可以通过移动+旋转坐标系,使得第 1 个宫殿在 \((0,0)\) 处,且方向为 \(x\) 轴正方向。

考虑到第 \(t\) 个时刻可以被感染的位置至少需要满足 \(|x|+|y|=t\),同时又不存在在同一个位置的宫殿。由此,我们可以唯一确定每一个王子的方向。

已经知道了方向,现在考虑如何计算答案。

如果两个点满足 \(x+y\)\(x-y\) 相同,且运动方向不平行,它们就会有一次相遇。如果两个点满足 \(x\)\(y\) 相同,且相向运动,它们就会有一次相遇。

对于每一个王子,我们找到它第一次被感染的时刻,则在此之后的所有相遇,他都会发生感染。这个过程类似 Dijkstra。

我们按照在 \(x+y\),\(x-y\),\(x\),\(y\) 这四种可能的相遇方式分开维护,则每一个点都会在某三个内。同时,不难发现每一次可能感染的是一段前缀或者后缀,赋上的权值形如对 \(x-b\)\(\min\),其中 \(b\) 为某一个固定权值,\(x\) 为每一次 Dijkstra 松弛是赋的权值。

这个信息可以使用线段树维护,时间复杂度 \(O(n\log n)\)

Day1 T3 フードコート

加入没有删除操作怎么做。我们相当于是要找在哪一个时刻,一个队伍的人超过了 \(B\)。可以扫描线序列轴来维护时间轴,这样可以使用线段树上二分来找到答案。

现在考虑删除操作,如果我们能够维护出来我们删去了多少个人,就可以通过修改询问的 \(B\) 来视为没有删除操作。但是每一个位置删除了多少个人并不好维护。但是来过多少人和剩下多少人是好维护的。而 \(删除人数=总人数-剩下人数\),这样就可以维护了。

时间复杂度 \(O(n\log n)\)

Day2 T1 逃走経路

详细版题解博客

可能的到达方式有两种:在一天之内到达和在若干天到达。

在若干天到达可以被拆分成,第一天,中间的若干整天,和最后一天。其中,第一天可以看作从 \(S\) 时刻开始倒着往回走,最后一天可以直接维护一个加了转移权值限制的最短路,中间的若干天可以使用最后一天的连通性再跑一边 floyd。

而对于在一天之内到达的情况,我们考虑每一条路径都会被某一条边作为最紧的限制限制住,我们枚举这条边,然后向前和向后拓展最短路,这样每一个点对之间都会得到 \(O(m)\) 条可能的最短路。去掉所有被偏序掉了的路径,就可以直接通过二分查找得到答案。

时间复杂度 \(O(n^2m\log m+Qn)\)

Day2 T2 道路の建設案

我们首先考虑二分答案找到第 \(k\) 大是多少。

由于曼哈顿距离不好维护,所以将坐标系旋转 \(45^\circ\) 之后变成切比雪夫距离。

我们将所有点按照 \(x_i\) 从小到大排序,这样对于 \(i\) 我们只需要统计所有 \(j<i\) 的点对即可。对于当前二分的答案 \(mid\),使用双指针维护出所有满足 \(x_i-mid\le x_j\)\(j<i\)\(j\) 对应的区间,使用 multiset 直接存储所有对应的 \(y_j\),然后我们逐个查找 \(y_j\in[y_i-mid,y_i+mid]\),如果当前满足条件的已经有 \(k\) 个了就直接返回,这样能够保证单次时间复杂度为 \(O(k\log n)\),这样就可以使用 \(O(k\log n\log V)\) 的时间得到第 \(k\) 大的值 \(ans\)。然后我们可以对于 \(ans-1\) 做一次和上面单次二分检验完全一致的操作,只是在这个过程中额外维护一下所有满足条件的点对的值是多少,这样就可以得到所有 \(\le ans-1\) 的距离的分布,不足 \(k\) 个的部分可以直接用 \(ans\) 补齐,这一部分的复杂度为 \(O(k\log n)\)

总体时间复杂度为 \(O(n\log n+k\log n\log V)\)

Day2 T3 買い物

神秘题,还没有做。

Day3 T1 古代の機械

首先,在第一个 X 左边和最后一个 Z 右边的字符必然不会对答案做出贡献。

然后剩下的每一个连续的 Y 的至多只能够有一个做出贡献,这个是答案的上界。

我们考虑如何能够取到这个上界:我们先找到最左边一个 X,将其左边的点都删去,然后找到最左侧的一个 Z,从右向左将 XZ 之间的字符删去,然后删去 Z

考虑这个过程为什么能够取到上界,由于我们找到的是最左侧的一个 Z,所以在这个 Z 之前的所有字符不是 X 就是 Y,这也就意味着对于每一个 Y 的连续段,我们删去其中最后一个的时候,它的左侧必然是 X,同时它的右侧就是我们找到的这个 Z,这个 Y 就会做贡献。

这样我们就只需要传输一个 \(01\) 串,用 \(1\) 来特殊标记我们找到的第一个 X 以及接下来的所有 Z 即可。

但是其实还有很多的没有意义的信息,例如对于一个连续段的 Z,完全可以从其中最后一个 Z 开始删去。考虑这样有什么好处:除了最左侧可能会出现 \(XZ\) 之外,所有的 \(1\) 必然都不会相邻。先使用一位特判掉 \(XZ\) 这种情况之后,整个 \(01\) 串就必然满足这一限制了。而不存在 \(1\) 相邻的 \(01\) 串个数可以通过递推知道是斐波那契数量级的,这样我们也很容易通过 DP 来得到每一个 \(01\) 串对应的字典序排名,也可以通过排名来得到这个 \(01\) 串,而我们需要的位数仅仅是 \(\left\lceil\log_2F_{n+2}\right\rceil \approx \log_2\left(\dfrac{1}{\sqrt{5}}\left(\dfrac{1+\sqrt{5}}{2}\right)^{n+2}\right)\approx 0.694(n+2)\le 70000\) 可以通过。

Day3 T2 ボディーガード

我们将每一个人的路径在 \(x-t\) 图像上表述出来,就都是斜率为 \(\pm 1\) 的线段。所以我们将坐标系旋转 \(45^\circ\) 使其变成平行于 \(x\) 轴或者 \(y\) 轴的直线。

将其离散化之后变成网格图。警卫在走到了格点之后,必然会沿着格线走,我们可以用 DP 来直接计算出从每一个格点出发的答案答案。现在的问题就是警卫先走到哪个格点上。

通过调整法可知,警卫必然先水平或者竖直走到某一条格线上,然后往后走到对应的格点上,然后就可以直接取 DP 值了。分别处理先水平走和先竖直走两种情况。每一种情况都可以对应为若干个一次函数在某一点取最大值,考虑直接使用李超线段树维护,时间复杂度 \(O((n^2+q)\log q)\)

Day3 T3 ビーバーの会合 2

对于奇数个点,答案必然为 \(1\)。对于偶数个点,我们就是要最大化两个点的数量相同的边的数量,而这些边必然构成一条链。

我们考虑如何找到这一条链的两个端点。我们看一个点最多可以为某一条边容纳多少个点:这个值应该等于断掉了某一条边之后,它所在的的连通块的大小的最小值,具体的就是断掉它最大的一个儿子。这个显然是一个下界,考虑为什么也是上界:如果它对应的连边不是断掉它最大的一个儿子,显然这条链的另一端能够选择到的点数必然小于这个值;如果断的是最大的儿子,这这个点能够选择的点数就是这个值。

所以我们只需要按照一定的顺序加入这些点,然后动态维护直径即可,时间复杂度 \(O(n\log n)\)

Day4 T1 イベント巡り 2

显然有一个贪心:每一次选择右端点最左的区间。这样能够取到可能的答案上界,而这个贪心跳的过程可以直接用倍增维护。

现在考虑如何找到字典序最小的答案:我们可以直接计算在选择第 \(i\) 个区间的情况下,其余的选择尽可能多的区间,能够取到答案,就贪心的选择。

用 set 维护当前还没有被选择的区间,然后每一次用倍增维护区间的答案即可,时间复杂度 \(O(n\log n)\)

Day4 T2 道案内 2

显然每个格子只能存储 12 种信息,将多个目的地的信息压缩到一个格子内很不现实,而我们可以看到 \(3\times 3\) 个格子,应该是每一个目的地对应一个格子,同时有一个标识符来表示哪个格子对应哪个目的地。

这样每一个格子对应的位置是稀疏的,所以每一个格子对应的方向需要在 \(3\times 3\) 的范围内都生效。除了以目的地位中心的 \(9\) 个格子很特殊之外,另外的格子都可以对应 4 个大方向,这样一共有 \(13\) 种本质不同的字符,加上标识符共 \(14\) 个,但是每个九宫格我们只用了 \(8\) 个格子。

但是考虑到中心的那 \(9\) 种标识符总共只会出现 \(7\) 个,也就意味着必然有 \(2\) 个是空余的,我们考虑对于这两个做文章。对于其中较小的那个,我们将所有大于它的数 \(-1\),然后再利用剩下的这个格子来记录是从那个数开始偏移的即可,一共需要 \(13\) 个数字。

我们可以通过调整每一个目的地对应那个格子集合来使得不会有任何一个目的地本身属于其对应的格子,这样原先中心的 \(9\) 个格子就变成了 \(8\) 个,就只需要 \(12\) 种数字了。

Day4 T3 最悪の記者 4

考虑树的情况怎么做:我们对于每一个点维护一个 DP 值 \(f_u\)\(u\) 的子树内,不改变根节点的情况下,不被修改的点的权值和是多少。

转移为 \(f_u=c_u+\max\limits_{S}\sum\limits_{v\in S}f_v\),其中 \(S\) 为满足 \(u\) 子树内,两两没有祖先后代关系,且 \(c_v\ge c_u\) 的集合。

发现这个 DP 可以使用线段树合并优化转移。

考虑最后树上的那个环怎么处理:环上的点数字必然全部相同,只需要枚举改成环上某权值,或改成全局最小值的代价即可。时间复杂度 \(O(n\log n)\)