SPOJ 375 Query on a tree (树链剖分+线段树)
2015-07-22 10:47
423 查看
题意:
给出一棵树,有两种操作:询问[u,v][u,v]的最大权值
然后更改第ii条边的权值为valval
解析:
这是树链剖分的入门题,昨天调试了半天才做出这题,我还是太弱了。>但是还是弄懂了什么是树链剖分树链剖分有先要进行两次dfs操作进行初始化。
第一个初始化操作,求得是每个节点的开头fa[u],每个节点的深度deep[u],以及每个节点的重儿子son[u]。
第二个初始化操作,求得是重链的头top[u],以及在每个节点在线段树中的位置id[u]。
为什么树链剖分会更快?
因为每次询问的时候,查询的点都是跳到重链的头,这样类似一个跳表,这样减少了中间访问的次数
怎么询问[u,v]的最值?
(1) 记tp1=top[u]tp1 = top[u],tp2=top[v]tp2 = top[v]。
(2) 当tp1!=tp2tp1 != tp2时:不妨设dep[tp1]>=dep[tp2]dep[tp1] >= dep[tp2],那么就更新u到tp1的父边的权值(log(n)log(n)),并使u=fa[tp1]u = fa[tp1]。
(3) 当tp1=tp2tp1 = tp2时:u与v在同一条重链上,若u与v不是同一点,就更新u到v路径上的边的权值(log(n)log(n)),否则修改完成。
查询的时候用线段树维护的是,当前点u,在线段树中的位置id[u]id[u],以及重链的头tp1,在线段树中的位置id[tp1]id[tp1],查询的就是区间就是 [id[u],id[tp1]][id[u],id[tp1]]
mymy codecode
[code]#include <cstdio> #include <cstring> #include <algorithm> #include <vector> #define ls (o<<1) #define rs (o<<1|1) #define lson ls, L, M #define rson rs, M+1, R using namespace std; const int N = 10005; struct Edge { int u, v, val; Edge() {} Edge(int u, int v, int val) : u(u), v(v), val(val) {} } edge ; int n; vector<int> G ; int deep , size , fa , id , son , top ; int dfs_clock; void init() { for(int i = 0; i <= n; i++) G[i].clear(); } void addEdge(int u, int v) { G[u].push_back(v); } void dfs1(int u, int pre, int de) { deep[u] = de; size[u] = 1; son[u] = 0; fa[u] = pre; for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if(pre == v) continue; dfs1(v, u, de+1); if(size[son[u]] < size[v]) son[u] = v; } } void dfs2(int u, int tp) { top[u] = tp; id[u] = ++dfs_clock; if(son[u]) dfs2(son[u], tp); for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if(v == fa[u] || v == son[u]) continue; dfs2(v, v); } } int maxv[N<<2]; inline void pushUp(int o) { maxv[o] = max(maxv[ls], maxv[rs]); } void build(int o, int L, int R) { maxv[o] = 0; if(L == R) return ; int M = (L + R)/2; build(lson); build(rson); pushUp(o); } void modify(int o, int L, int R, int pos, int val) { if(L == R) { maxv[o] = val; return ; } int M = (L + R)/2; if(pos <= M) modify(lson, pos, val); else modify(rson, pos, val); pushUp(o); } int query(int o, int L, int R, int ql, int qr) { if(ql <= L && R <= qr) return maxv[o]; int M = (L + R)/2, ret = 0; if(ql <= M) ret = max(ret, query(lson, ql, qr)); if(qr > M) ret = max(ret, query(rson, ql, qr)); return ret; } int find(int u, int v) { int tp1 = top[u], tp2 = top[v]; int ans = 0; while(tp1 != tp2) { if(deep[tp1] < deep[tp2]) { swap(tp1, tp2); swap(u, v); } ans = max(ans, query(1, 1, dfs_clock, id[tp1], id[u])); u = fa[tp1]; tp1 = top[u]; } if(u == v) return ans; if(deep[u] > deep[v]) swap(u, v); return max(ans, query(1, 1, dfs_clock, id[son[u]], id[v])); } int main() { //freopen("in.txt", "r", stdin); int T; scanf("%d", &T); while(T--) { scanf("%d", &n); init(); int u, v, val; for(int i = 1; i < n; i++) { scanf("%d%d%d", &u, &v, &val); edge[i] = Edge(u, v, val); addEdge(u, v); addEdge(v, u); } dfs_clock = 0; dfs1(1, 0, 1); dfs2(1, 1); build(1, 1, dfs_clock); for(int i = 1; i < n; i++) { if(deep[edge[i].v] < deep[edge[i].u]) swap(edge[i].v, edge[i].u); modify(1, 1, dfs_clock, id[edge[i].v], edge[i].val); } char oper[10]; while(~scanf("%s", oper)) { if(oper[0] == 'D') break; if(oper[0] == 'Q') { scanf("%d%d", &u, &v); printf("%d\n", find(u, v)); }else if(oper[0] == 'C') { scanf("%d%d", &u, &val); modify(1, 1, dfs_clock, id[edge[u].v], val); } } } return 0; }
相关文章推荐
- Target runtime com.genuitec.runtime.generic.jee60 is not defined的解决方案
- What are the best practices for building something like a News Feed?
- UIViewAdditions(一个非常方便的工具类用它)
- 关于configure中build,target,host中的若干问题
- 【从零开始学NGUI 】 (二)Label
- UIView frame, bounds and center
- RMQ(Range Minimum/Maximum Query)问题——ST算法
- UESTC 360 Another LCIS(线段树区间更新)
- 【UIKit】-3-UIAccessibility - 元素可访问性,辅助功能
- HDU 5288 OO's sequence (2015多校第一场 二分查找)
- HDU 5288 OO‘s sequence (技巧)
- 【从零开始学NGUI 】 (一)安装NGUI插件
- HDU 1159 Common Subsequence
- 自定义UITableViewCell 上按钮点击事件处理
- 【UIKit】-2- UIAccelerometer-加速计事件
- HDU 5288 OO’s Sequence(多校第一场1001)
- 关于mule中使用jdbc时报No Suitable Driver found错误的问题
- Convert UOM values
- No suitable driver found for jdbc:mysql://localhost:3306/test
- 【UIKit】-1- UIKitDefines.h - 跨平台,包容 C 库