SPOJ - QTREE Query on a tree 树链剖分
题目链接:
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=13013
题意:
给你一颗树,现在有两个操作,一种是改变某条边的权值,一种是查询点u到v之间的路径的最大边权。
题解:
树链剖分入门题。
我看的一些博客:
http://www.tuicool.com/articles/ee2QZf6
http://blog.csdn.net/y990041769/article/details/40348013
http://www.cnblogs.com/lidaxin/p/5184627.html
ppt:http://wenku.baidu.com/view/a088de01eff9aef8941e06c3.html
树链剖分只是把一些点映射到一个区间(一个重链相当于映射到了一个区间,轻链这是映射到了孤立的一些点),然后需要线段树或者rmq之类的数据结构基础来维护一些值。
主要代码就是两个dfs加一个solve(查询函数),两个dfs其实都挺简单的,中点把查询方法掌握了就基本ok了。
代码:
#include<iostream> #include<cstring> #include<cstdio> #include<vector> #include<queue> #include<utility> using namespace std; const int maxn = 22222; const int INF = 0x3f3f3f3f; struct Edge { int u, v, w; }egs[maxn]; vector<pair<int, int> > G[maxn]; int val[maxn], fat[maxn], dep[maxn], siz[maxn], son[maxn], top[maxn], id[maxn]; int n; //求val,fat,dep,siz,son; void dfs(int u, int f, int d, int va) { val[u] = va; fat[u] = f; dep[u] = d; siz[u] = 1; int ma = -INF; for (int i = 0; i < G[u].size(); i++) { int v = G[u][i].first; if (v == f) continue; dfs(v, u, d + 1, G[u][i].second); siz[u] += siz[v]; if (ma < siz[v]) { son[u] = v; ma = siz[v]; } } } //求top,id int _tot; void dfs2(int u, int f, int t) { top[u] = t; id[u] = ++_tot; if (son[u]) dfs2(son[u], u, t); for (int i = 0; i < G[u].size(); i++) { int v = G[u][i].first; if (v == f || v == son[u]) continue; //轻链的下端点top等于它自己 dfs2(v, u, v); } } #define lson (o<<1) #define rson ((o<<1)|1) #define M (l+(r-l)/2) int maxv[maxn << 2]; int _p, _v; void update(int o, int l, int r) { if (l == r) { maxv[o] = _v; } else { if (_p <= M) update(lson, l, M); else update(rson, M + 1, r); maxv[o] = max(maxv[lson], maxv[rson]); } } int ql, qr, _max; void query(int o, int l, int r) { if (ql <= l&&r <= qr) { _max = max(_max, maxv[o]); } else { if (ql <= M) query(lson, l, M); if (qr > M) query(rson, M + 1, r); } } // int solve(int u, int v) { int f1 = top[u], f2 = top[v]; int ret = -INF; while (f1 != f2) { //printf("f1:%d,f2:%d\n", f1, f2); if (dep[f1] < dep[f2]) { swap(f1, f2); swap(u, v); } ql = id[f1], qr = id[u], _max = -INF; query(1, 1, n); ret = max(ret, _max); u = fat[f1]; f1 = top[u]; } //printf("u:%d,v:%d\n", u, v); if (u == v) return ret; if (dep[u] > dep[v]) swap(u, v); ql = id[son[u]], qr = id[v], _max = -INF; query(1, 1, n); ret = max(ret, _max); return ret; } void init() { for (int i = 1; i <= n; i++) G[i].clear(); memset(son, 0, sizeof(son)); _tot = 0; } int main() { int tc; scanf("%d", &tc); while (tc--) { scanf("%d", &n); init(); for (int i = 1; i < n; i++) { scanf("%d%d%d", &egs[i].u, &egs[i].v, &egs[i].w); G[egs[i].u].push_back(make_pair(egs[i].v, egs[i].w)); G[egs[i].v].push_back(make_pair(egs[i].u, egs[i].w)); } dfs(1, -1, 1, -INF); dfs2(1, -1, 1); //for (int i = 1; i <= n; i++) printf("id:%d\n", id[i]); for (int i = 1; i <= n; i++) { _p = id[i], _v = val[i]; update(1, 1, n); } char cmd[11]; int x, y; while (scanf("%s", cmd) == 1) { if (cmd[0] == 'D') break; scanf("%d%d", &x, &y); if (cmd[0] == 'Q') { printf("%d\n", solve(x, y)); } else if (cmd[0] == 'C') { int t = fat[egs[x].v] == egs[x].u ? egs[x].v : egs[x].u; _p = id[t], _v = y; update(1, 1, n); } } if(tc) puts(""); } return 0; } /* 4 1 2 1 1 3 2 3 4 3 QUERY 1 2 QUERY 1 3 QUERY 3 4 DONE */