这是括号序动态维护的方法,这里不讲。 注意到一个结论:设S,T(S∩T=∅)S,T(S∩T=∅)为两个树中的点集。 记f(S)f(S)为一个大小为22集合,其中两个点分别为SS集合中直径的两个端点(多个取任意)。 则有结论:∃x,y∈f(S)∪f(T),x≠y∃x,y∈f(S)∪f(T),x≠y,满足x,yx,y是S∪TS...
树上两点距离可以表示为dis[u]+dis[v]−2×dis[LCA(u,v)]dis[u]+dis[v]−2×dis[LCA(u,v)] 考虑维护一条长为2N−12N−1的序列A[i]=dep[dfn[i]]A[i]=dep[dfn[i]]。所以求直径的问题可以转化为求 max1≤l≤r≤2N−1{A[l]+A[r]−2×minl≤k≤r{A[k]}}max1≤l≤r≤2...
看到有别的写法,维护区间直径,一个点的时候就是直径端点就是自己,两个区间合并的时候,新的直径肯定是一个区间的某个直径端点和另一个区间的某个直直径端点,就取个max合并就好了。 不过是2log的。
树的直径可以通过两次 dfs() 的方法求得。换句话说,到任意点最远的点,一定是直径的某个端点(反证法)。 • 因此原问题转化为动态维护直径,然后再支持询问两个点的距离,后者可以 dfs 序 + lca + 树状数组。 参考代码: View Code
首先,我们可以知道,对于静态的树我们可以通过两遍dfs求出直径及其端点。 然后距离某一点最远点一定是直径端点,这个就不说了。。。 所以问题变成了支持修改边权,维护树的直径和端点,以及求两点距离。 后者可以这样看:和树链剖分一样,先跑一遍dfs,这样就可以知道某个节点的及其子树,那么dis【u】+=x相当于u的子...
专出神题的xyz。支持删加边、修改点权、维护树的直径。LCT 需要额外记录子树信息。用一个堆维护。#include#include#include#include#include#includeusing namespace std;#define rep(i,x,y) for(i=x;i=y;i.