[ZJOI2019]语言 题解
懒得打代码所以学了做法口胡了。。。其实完全不难想的降智了。。。
考虑一条链,直接线段树维护每个点能到达的最远距离,用 sgt 维护是 \(\mathcal {O}(n\log_2n)\) 的,结合暴力有 \(60pts\)。(这是省选 D2T2,为什么部分分给这么足)
考虑对于一个点,我们知道了几条链经过它,怎么算它提供的贡献。发现它提供的贡献一定是一个连通块,并且刚好覆盖完链的端点。稍微观察一下发现将点按 \(\mathrm {dfn}\) 序排序,\(\mathrm {ans}=\sum_{i=1}^n d_i-\sum_{i=1}^{n-1} d_{lca(i,i+1)}-d_{lca(1,n)}\)。这个式子就很妙,我们就不用每次合并 \(\mathrm {lca}\) 了。
如果我们用树链剖分或者树分块,每次考虑将链差分,用 sgt 合并。根据上面那个式子,发现我们需要用线段树维护 \(\mathrm {ans、dfn_{min}、dfn_{max}}\)。由于是单点修改,所以这样的 sgt 是合理的。
用欧拉序st表求 lca,时间复杂度:\(\mathcal {O}(n\log_2 n)\)。
找个时间打吧。。