codeforces 1110F
题解:
正解做法比较简单,考虑离线之后,相邻两个节点之间的答案是有关系的
发现从父亲移到儿子后,改变的距离对于当前节点子树内和子树外的是一样的
所以线段树维护一下区间加减取max就可以了
另外的做法1:
过不了,考虑分块
对连续的叶子分成一个块,维护每个点到这个点的距离,可以多源最短路nlogn
然后查询的时候零散的要查找两个点之间的距离,这个可以O(1)rmq
所以块大小设成$\sqrt{nlogn}$是$q\sqrt{nlogn}$
理论复杂度1.5e9。。。别想过了
做法2:
这个做法可以在线(正解可持久化一下当然也可以),比正解麻烦
考虑询问一个点x,那么它儿子内的点我们只需要查到根距离最短的就可以了
然后我们去考虑枚举叶子和当前点的$lca$,这时候我们发现我们只需要查找离$lca$最近的那个点就行了
但是$lca$暴力枚举只有在树是随机的情况下才是对的
我们把距离写成$dis[x]-dis[lca]+dis2[lca]$ 其中$dis$表示到根距离,$dis2$表示子树中到它的最短距离
如果我们知道$dis2$我们就可以维护了
我们把问题按照$dfs$序和$x$的$dfs$序的大小关系分成两类
以小于为例
令$dis2[lca]$为$lca$子树内$dfs$序小于$dfs[x]$到$lca$的最短距离
那么我们会发现,对于$x$连续的一段祖先,我们考虑它就是考虑$dis2$
会发现对于不同节点,查询同一个节点$k$的$dis2[k]$是不同的
所以我们用$dis2[k]$记录原本应该$dis2[fa[k]]$记录的东西,那么就唯一了
倍增维护
直到$lca(第一个叶子,x)$这个节点可能是不完整的
所以要特殊查一下
查的话可以可持久化线段树合并维护一下每个点子树内dfs为k的值,然后区间查询就可以了
起始位置如果没有包含所有比$dfs[x]$小的节点也要特殊查一下
大于同理
最后复杂度还是$nlogn$的