[eJOI2020 Day1] Fountain 题解

发布时间 2023-10-30 21:21:14作者: TuSalcc

题目链接

原题做法:用单调栈求出每个圆盘中的水溢出后会 直接 流到哪个圆盘,因为每个圆盘中的水向下流有且仅有一个圆盘会 直接 接住它(将水池视作直径和容量都是正无穷的一个圆盘),因此构成了一棵树,根节点即为水池,每个点有点权,即该点代表的圆盘的容量。记 \(dis_{i,j}\) 表示节点 \(i\) 到节点 \(j\) 的路径所经过的点的点权和,则每一次询问 \(r,v\) 可以抽象成求一个点 \(ans\),使得 \(ans\)\(r\) 的祖先且 \(v > dis_{r, temp}\)\(v \leq dis_{r,ans}\),其中 \(temp\)\(ans\) 的儿子、\(r\) 的祖先。显然倍增是个好方法。时间复杂度 \(O(nlog_2 n+Qlog_2 n)\),秒切。


显然,这是一道水题,因此这篇题解主要不是 A 了这题,而是讲一些题外话。

首先,在赛时第一眼看错题目了,以为前面的询问对后面的询问时有影响的。那有影响时该如何解决呢?显然,问题变简单了。依旧先用单调栈构建出一棵树,然后对于每一次询问直接暴力一个节点一个节点地跳,逐个更改。但是这样显然会超时,怎么办呢?我们分析每次询问,发现若向上跳了 \(n\) 个节点,则前 \(n-1\) 个节点一定是被灌满的。而被灌满的节点进来多少水就会出去多少水,是无用的,因此,我们考虑每次询问时顺便将灌满的节点和其父亲节点合并,即消除其影响。因为每个节点被灌满一次后就被合并,所以最多合并 \(n\) 次,故 \(Q\) 次查询的总时间复杂度为 \(O(Q+n)\)(其中 \(Q\) 是指每次询问都有至多一个未被灌满的节点)。而预处理用单调栈建树的时间复杂度为 \(O(n)\),因此可以通过。

而后又想了想本题可不可以带修。

若仅改变某一圆盘的直径。蒟蒻暂时只想到了 \(O(n)\) 的时间复杂度重构树,没想到更优解。

改变一段连续的圆盘的直径同上。还是我太菜了

若仅改变某一圆盘的容量,不难发现倍增数组基本整个都要变动。此时我们看问题:对于一棵树,查询的是树上某一个自下而上的路径,同时也是带修的,不难想到树链剖分。每条链上维护的内容为带修区间和,故用线段树维护。时间复杂度 \(O(nlog_2^2n)\),可过。

若改变的是一段连续的圆盘的容量,显然如果用树链剖分则需要改变很多条链的内容,时间炸了。依然,蒟蒻没有想到解法。

带修的还是需要再想想。待更新……