APIO 2019 解题报告

奇怪装置

解题思路

考虑循环节大小,设循环节长度为 \(S\),二元组分别为两个函数表示

\[x(t)=(t+\lfloor \frac tB\rfloor) \; mod \; A \]

\[y(t)=t \; mod \; B \]

\[x(t+S)=(t+S+\lfloor \frac {t+S}B\rfloor) \; mod \; A \]

\[y(t+S)=(t+S) \; mod \; B \]

\[t\equiv t+S \mod B \]

显然

\[S\mod B=0 \]

那么令\(S=kB\)

\[x(t+kB)\equiv (t+\lfloor \frac tB\rfloor+kB+k)\mod A \]

\[k(B+1)\mod A=0 \]

显然

\[k=\frac A{\text{gcd}(B+1,A)} \]

循环节大小为

\[B\cdot \frac A{\text{gcd}(B+1,A)} \]

然后就是离散化后线段覆盖即可

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

参考程序

路灯

解题思路

我们称能够相互到达的子段为关键段。

维护关键段可以用线段树维护。

先考虑断开某一个关键段 \([l,r]\) 的某一条边 \(k\),那么这个操作只对 \([l,k]\)\([k+1,r]\) 内的答案有贡献。同理加入这条边也只对这两个关键段有贡献。

考虑将这个贡献差分,就得到了:

  • 若插入,在第 \(i\) 个时刻,\([l,k]\)\([k+1,r]\) 内的答案 \(-i\)
  • 若删除,在第 \(i\) 个时刻,\([l,k]\)\([k+1,r]\) 内的答案 \(+i\)

一个特判,如果每个询问的最后时刻 \(t\),若这两个点是联通的,那么我们需要 \(+t\)

接下来,我们将两个关键段抽象成二维坐标系内的 \(x\) 轴和 \(y\) 轴,也就是每次在 \((l,k+1,k,r)\) 内的矩形进行带权修改。

因此考虑离线分治计算答案,是一个二维数点问题。

时间复杂度 \(\Theta (n \log^2n)\)

参考程序

桥梁

解题思路

子任务 链

本质是一个序列问题。

你可以发现每一次的操作是进行一次向左边扩展和向右边扩展,找到第一条不满足的边。也就是说你需要找到一个包含起点的最大区间,满足在上面的所有边权都满足 \(\geq y\)

因为支持修改操作,所以考虑用二分答案,线段树查询的方法在 \(O(nlog^2n)\) 的时间解决。

子任务 只有查询

我们假设联通块中最小的边权为 \(min\),那么某一个起点开始能够遍历整个联通块的充要条件是 \(min \ge y\)

也就是最小边的边权 \(\ge y\),这就容易想到用 \(Kruscal\) 重构树来实现这个过程。

建立出 \(Kruscal\) 重构树之后,以每一个节点为根节点的子树,都可以被以根节点为起点的路径包含,所以只需要倍增找到最后一个满足条件的祖先节点,然后其子树大小即为答案。

也可以采用离线做法,将操作离线后,按照 \(y\) 值从大到小查询,将所有的边按照顺序加入到并查集中,答案就是联通块大小

正解

采用「子任务 只有查询」中的做法,考虑暴力。

我们按照询问分块,在当前块中的所有操作都相当于和前面所有块的到的新图重新暴力求一遍答案,然后更新为新图

将当前块中不需要修改的边加入到联通块中,考虑修改的边,将在当前操作之前的每一条边最后一次操作得到的权值和标准值 \(y\) 进行比较,否则视为未被修改。

每一次操作,同一条边可能被不同的修改操作,所以考虑要可撤销并查集

参考程序

posted @ 2022-06-27 14:33  Ayersz  阅读(53)  评论(0)    收藏  举报