線段樹求直徑可以求任意子樹(包括連子樹都不算的分散節點集合)的直徑,適用範圍廣。
線段樹的每個節點所對應的區間$[l, r]$,指代了$dfn$在$[l, r]$內節點,其中線段樹上每個節點儲存了$diam$(當前區間直徑)及$lp, \ rp$(當前直徑對應的左右端點),每次$merge$操作分為全左區間、全右區間和橫跨兩個區間作討論,對於第三種情況,選擇兩側原直徑端點求$dist$取最值即可,正確性顯然,查詢直接通過$dfn$查詢即可。
當然可能有一些區間內的點不連通,先當作它們連通即可。
對於刪除某些子樹,相當於把整棵樹分為$n$部分,查詢每個部分,全部$merge$起來即可。
·例題
snow的追尋
1 #include 2 #include 3 #include 4 #include 5 #include 6snow的追尋7#define lson root << 1
8#define rson root << 1 | 1910
using
namespace
std;
1112
const
int maxn = 1e05 + 10;13
const
int maxm = 1e05 + 10;14
15struct
linkedforwardstar ;
2021 linkedforwardstar link[maxm << 1
];22
int head[maxn]= ;
23int size = 0;24
25void insert (int u, int
v) 31
32const
int root = 1;33
34int
deep[maxn];
35int
size[maxn];
36int val[maxn << 1
];37
intdfn[maxn], ddfn[maxn];
38int
rank[maxn];
39int dfsord = 0, dod2 = 0;40
41void dfs (int root, int
father) 57}
5859
int st[maxn << 1][30
];60
61void
rmq ()
6970
int query (int l, int
r) 74
75int dist (int x, int
y) 82
83struct
node
9192 node (int fdiam, int flp, int
frp) :
93diam (fdiam), lp (flp), rp (frp) {}
94} ;
9596 node tree[maxn << 2
];97
9899
node merge (node s1, node s2)
114115
void build (int root, int left, int
right)
123124
int mid = (left + right) >> 1
;125
build (lson, left, mid);
126 build (rson, mid + 1
, right);
127128 tree[root] =merge (tree[lson], tree[rson]);
129}
130131 node query (int root, int left, int right, int l, int
r) 143
144int
n, q;
145146
intgetnum ()
157158
intmain ()
168169 dfs (root, 0
);170
rmq ();
171172 build (root, 1
, dfsord);
173for (int case = 1; case <= q; case ++)
191192
return0;
193}
194195
/*196
5 2197
1 3198
3 2199
3 4200
2 5201
2 4202
5 4203
*/
求樹的直徑
歡迎來踩本人部落格 樹的直徑 就是樹上最長路 方法 求兩邊dfs即可 步驟 1.從任意一點進行dfs,然後找到乙個最長路徑,記錄最遠點u 2.然後從u再進行dfs,找最長路徑,記錄一點v。u,v 就是樹的直徑 第四屆藍橋杯a組 證明 我們可以看出圖中,樹的直徑是 4 2 5 長度為9.我們一開始選定...
求樹的直徑
歡迎來踩本人部落格 樹的直徑 就是樹上最長路 方法 求兩邊dfs即可 步驟 1.從任意一點進行dfs,然後找到乙個最長路徑,記錄最遠點u 2.然後從u再進行dfs,找最長路徑,記錄一點v。u,v 就是樹的直徑 第四屆藍橋杯a組 證明 我們可以看出圖中,樹的直徑是 4 2 5 長度為9.我們一開始選定...
求樹的直徑
由於之前寫了一篇部落格,用到了樹的直徑卻沒有求。在咕咕咕了n多天之後決定寫這篇部落格。樹的直徑就是樹中最長的一條路。求樹的直徑我只會一種方法 據說dalao都會2種 隨便找乙個點跑一遍最短路,找到離他最遠的節點a,然後從a節點繼續跑最短路,再次找到乙個離a最遠的節點b,a和b分別是直徑的兩個端點,他...