樹鏈剖分並不是乙個複雜的演算法或者資料結構,只是能把一棵樹拆成鏈來處理而已,換一種說法,樹鏈剖分只是***資料結構/演算法在樹上的推廣,或者說,樹鏈剖分只是把樹hash到了幾段連續的區間上。
主要參考kuangbin :
以及 第二個其中的修改操作的解釋好像有問題,
其例子中查詢11和10 的實際的遍歷和他的解釋有不同,
原來是:
當要修改11到10的路徑時。
第一次迭代:u = 11,v = 10,f1 = 2,f2 = 10。此時dep[f1] < dep[f2],因此修改線段樹中的5號點,v = 4, f2 = 1;
第二次迭代:dep[f1] > dep[f2],修改線段樹中10--11號點。u = 2,f1 = 2;
第三次迭代:dep[f1] > dep[f2],修改線段樹中9號點。u = 1,f1 = 1;
第四次迭代:f1 = f2且u = v,修改結束。
我認為應該是:
第一次迭代:u = 11,v = 10,f1 = 2,f2 = 10。此時dep[f1] < dep[f2],因此修改線段樹中的5號點,v = 4, f2 = 1;
第二次迭代:dep[f1] > dep[f2],修改線段樹中9--11號點。u = 1,f1 = 1;
第三次迭代:f1 = f2且u != v,修改線段樹1號點,v= 1,f2 = 1; 修改結束
const double eps = 1e-10;
const int maxn = 10010;
struct edge;
edge adj[maxn * 2];
int head[maxn], tol;
int top[maxn];///top[v]表示v所在重鏈的頂端定點
int fa[maxn];///fa[v]表示v的父節點,沒有為-1
int deep[maxn];///deep[v]表示v在樹中的深度,根點為1
int num[maxn];///num[v]表示以v為根的子樹的節點數
int son[maxn];///重兒子,沒有為-1
///int sonid[maxn]
int fp[maxn];///和p陣列相反
int pos;
void init()
void add_edge(int u, int v, int l)
void dfs1(int u, int pre, int d)///求出fa, deep, num, son
}}void getpos(int u, int sp)///top, p, fp
}///線段樹求最大值
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
int s[maxn << 2];
void pushup(int rt)
void update(int p, int x, int l, int r, int rt)
int m = (l + r) >> 1;
if (p <= m) update(p, x, lson);
else update(p, x, rson);
pushup(rt);
}int query(int l, int r, int l, int r, int rt)
int m = (l + r) >> 1;
int ret = 0;
if (l <= m) ret = max(ret, query(l, r, lson));
if (r > m) ret = max(ret, query(l, r, rson));
return ret;
}int find(int u, int v)
tmp = max(tmp, query(p[fu], p[u], 1, pos, 1));
u = fa[fu]; fu = top[u];
}if (u == v) return tmp;
if (deep[u] > deep[v]) swap(u, v);
return max(tmp, query(p[son[u]], p[v], 1, pos, 1)); ///如果是點剖分的話query(p[u], p[v], 1, pos, 1)
}int n;
int e[maxn][3];
int main ()
dfs1(1, -1, 1);
getpos(1, 1);
clr(s, 0);///初始化線段樹
fe(i, 1, n - 1)
char op[10];
int u, v;
while (scanf("%s", op) == 1)
}return 0;
}
SPOJ375 樹鏈剖分
題目 query on a tree 題意 給定一棵樹,告訴了每條邊的權值,然後給出兩種操作 1 把第i條邊的權值改為val 2 詢問a,b路徑上權值最大的邊 分析 本題與hdu3966差不多,區別就是 hdu3966是告訴樹中點權的值,這裡是邊權。所以我們可以轉化,用邊的孩子節點來表示該邊。inc...
spoj375 樹鏈剖分
第一次寫樹鏈剖分的題目,下面說下我對樹鏈剖分的理解 以spoj為例,題意是給你一棵樹,有兩種操作,一種是修改某條邊的權值,一種是詢問節點a到節點b之間的路徑上所有邊的最大路徑。處理以上所有的資訊只需要兩個dfs就可以 第乙個dfs,dfs1處理father,size,depth,son 如下 voi...
SPOJ375 樹鏈剖分
題目 query on a tree 題意 給定一棵樹,告訴了每條邊的權值,然後給出兩種操作 1 把第i條邊的權值改為val 2 詢問a,b路徑上權值最大的邊 分析 本題與hdu3966差不多,區別就是 hdu3966是告訴樹中點權的值,這裡是邊權。所以我們可以轉化,用邊的孩子節點來表示該邊。inc...