第一次寫樹鏈剖分的題目,下面說下我對樹鏈剖分的理解
以spoj為例,題意是給你一棵樹,有兩種操作,一種是修改某條邊的權值,一種是詢問節點a到節點b之間的路徑上所有邊的最大路徑。
處理以上所有的資訊只需要兩個dfs就可以
第乙個dfs, dfs1處理father, size, depth, son
**如下:
void dfs1(int u, int f, int d)//計算depth, size, son, father}}
}
第二個dfs,dfs2處理top[i], id[i],構造出重鏈,**如下:
void dfs2(int u, int tp)
for(int i = 0; i < v[u].size(); i++)
}}
spoj完整ac**如下:
#include
using
namespace
std;
const
int maxn = 10005;
int n;//節點個數
struct edgeedge[maxn];//儲存邊
vector
v[maxn];//儲存圖
int top[maxn];//該節點所在重鏈的第乙個頭節點
int depth[maxn];//節點的深度
int size[maxn];//以該節點為根節點的子樹所有節點的個
int father[maxn];//節點的父節點
int id[maxn];//節點的父邊
int son[maxn];//節點的重兒子
int cnt;
void init()
memset(son, -1, sizeof(son));
cnt = 0;
}void dfs1(int u, int f, int d)//計算depth, size, son, father}}
}void dfs2(int u, int tp)
for(int i = 0; i < v[u].size(); i++)
}}struct nodenode[4 * maxn];
void pushup(int i)
void build(int i, int l, int r)
int f = i;
i <<= 1;
int mid = (l + r)>>1;
build(i, l, mid);
build(i|1, mid + 1, r);
pushup(f);
}void update(int i, int loc, int value)
int f = i;
i <<= 1;
if(loc <= node[i].r) update(i, loc, value);
else update(i|1, loc, value);
pushup(f);
}int query(int i, int l, int r)
int solve(int u, int v)
else
f1 = top[u];
f2 = top[v];
}if(u == v) return ans;
if(depth[u] < depth[v]) swap(u, v);
ans = max(query(1, id[son[v]], id[u]), ans);
return ans;
}int main()
dfs1(1, 1, 0);
dfs2(1, 1);
for(int i = 1; i < n; i++)//求解每個點的父邊
rank[id[u]] = edge[i].w;
}rank[1] = 0;
char op[10];
build(1, 1, cnt);
while(scanf("%s", op) == 1)
else
if(op[0] == 'c')}}
return
0;}
SPOJ375 樹鏈剖分
題目 query on a tree 題意 給定一棵樹,告訴了每條邊的權值,然後給出兩種操作 1 把第i條邊的權值改為val 2 詢問a,b路徑上權值最大的邊 分析 本題與hdu3966差不多,區別就是 hdu3966是告訴樹中點權的值,這裡是邊權。所以我們可以轉化,用邊的孩子節點來表示該邊。inc...
SPOJ375 樹鏈剖分
題目 query on a tree 題意 給定一棵樹,告訴了每條邊的權值,然後給出兩種操作 1 把第i條邊的權值改為val 2 詢問a,b路徑上權值最大的邊 分析 本題與hdu3966差不多,區別就是 hdu3966是告訴樹中點權的值,這裡是邊權。所以我們可以轉化,用邊的孩子節點來表示該邊。inc...
SPOJ 375 樹鏈剖分
點選開啟鏈結 題意 給個樹和樹上的權值,兩個操作,q u v,問u到v的邊上的最大權值,c u v,將第u條邊的權值改為v 思路 今天學了學樹鏈剖分,這題是個檢驗模版的題目,理論我是解釋不清楚的,自己在九野聚聚那學來的乙份模版 include include include include incl...