樹鏈剖分 375 Query on a tree

2021-09-30 10:34:52 字數 2387 閱讀 4852

樹鏈剖分並不是乙個複雜的演算法或者資料結構,只是能把一棵樹拆成鏈來處理而已,換一種說法,樹鏈剖分只是***資料結構/演算法在樹上的推廣,或者說,樹鏈剖分只是把樹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...