给出一个序列 \(a\),若对于 \(i<j\) 有 \(a_i<a_j\) 则连一条 \(i\to j\) 的边,求联通块个数。
支持单点修改,保证任意时刻 \(a\) 互不相等。
\(\rm Sol:\)
先做一点观察,我们发现,连通块一定是一个区间。
对于 \((i,j)\) 假设两者之间有边,那么显然中间的点都与两者有边。
于是问题等价于存在分界点,等价于分界点的数量 \(+1\)
分界点的判定条件为不存在边跨过他,即左边最大值小于右边最小值。
接下来又来一个很神的转换,考虑枚举权值,对于 \(w\),将小于 \(w\) 的权值置为 \(0\),大于 \(w\) 的权值置为 \(1\),那么最后其可以得到一个分界点,其合法等价于序列会构成 111000...
方便起见,设 \(a_0=\infty,a_{n+1}=0\),考虑对于每个 \(w\),我们维护其是否在序列中出现,以 \(w\) 为视角进行观察,序列中的 10
数量,容易发现至少有一对 10
,且 10
数量恰好为 \(1\) 的 \(w\) 就是我们所求,考虑通过线段树维护,当一次修改将 \(a_i\) 改为 \(x\) 之后,我们将步骤拆开,视为将 \(a_i\) 改为 \(0\),再改为 \(x\),对于 \(w\in [a_{i+1},a_i]\) 的 \(w\),本次修改会减少一组 10
,而对于 \(w\in [a_i,a_{i-1}]\) 的 \(w\),本次修改亦减少一组 10
,注意到线段树直接维护难以处理区间修改的标记下传,但是注意到不存在 \(0\) 对 10
,所以我们直接维护最小值且存在的出现次数即可。
原文:https://www.cnblogs.com/Soulist/p/13656477.html