专题总结:树链剖分入门介绍
来源:互联网 发布:全知之眼 编辑:程序博客网 时间:2024/06/05 20:00
**数据规模大时,递归可能会爆栈,而非递归dfs会很麻烦,所以可将两个dfs改为宽搜+循环。即先宽搜求出fa、dep,然后逆序循环求出siz、son,再顺序循环求出top和w。
题目:spoj375、USACO December Contest Gold Divison, "grassplant"。
#include <cstdio>#include <algorithm>#include <iostream>#include <string.h>using namespace std;const int maxn = 10010;struct Tedge{ int b, next; } e[maxn * 2];int tree[maxn];int zzz, n, z, edge, root, a, b, c;int d[maxn][3];int first[maxn], dep[maxn], w[maxn], fa[maxn], top[maxn], son[maxn], siz[maxn];char ch[10];void insert(int a, int b, int c){ e[++edge].b = b; e[edge].next = first[a]; first[a] = edge;}void dfs(int v){ siz[v] = 1; son[v] = 0; for (int i = first[v]; i > 0; i = e[i].next) if (e[i].b != fa[v]) { fa[e[i].b] = v; dep[e[i].b] = dep[v]+1; dfs(e[i].b); if (siz[e[i].b] > siz[son[v]]) son[v] = e[i].b; siz[v] += siz[e[i].b]; }}void build_tree(int v, int tp){ w[v] = ++ z; top[v] = tp; if (son[v] != 0) build_tree(son[v], top[v]); for (int i = first[v]; i > 0; i = e[i].next) if (e[i].b != son[v] && e[i].b != fa[v]) build_tree(e[i].b, e[i].b);}void update(int root, int lo, int hi, int loc, int x){ if (loc > hi || lo > loc) return; if (lo == hi) { tree[root] = x; return; } int mid = (lo + hi) / 2, ls = root * 2, rs = ls + 1; update(ls, lo, mid, loc, x); update(rs, mid+1, hi, loc, x); tree[root] = max(tree[ls], tree[rs]);}int maxi(int root, int lo, int hi, int l, int r){ if (l > hi || r < lo) return 0; if (l <= lo && hi <= r) return tree[root]; int mid = (lo + hi) / 2, ls = root * 2, rs = ls + 1; return max(maxi(ls, lo, mid, l, r), maxi(rs, mid+1, hi, l, r));}inline int find(int va, int vb){ int f1 = top[va], f2 = top[vb], tmp = 0; while (f1 != f2) { if (dep[f1] < dep[f2]) { swap(f1, f2); swap(va, vb); } tmp = max(tmp, maxi(1, 1, z, w[f1], w[va])); va = fa[f1]; f1 = top[va]; } if (va == vb) return tmp; if (dep[va] > dep[vb]) swap(va, vb); return max(tmp, maxi(1, 1, z, w[son[va]], w[vb])); //}void init(){ scanf("%d", &n); root = (n + 1) / 2; fa[root] = z = dep[root] = edge = 0; memset(siz, 0, sizeof(siz)); memset(first, 0, sizeof(first)); memset(tree, 0, sizeof(tree)); for (int i = 1; i < n; i++) { scanf("%d%d%d", &a, &b, &c); d[i][0] = a; d[i][1] = b; d[i][2] = c; insert(a, b, c); insert(b, a, c); } dfs(root); build_tree(root, root); // for (int i = 1; i < n; i++) { if (dep[d[i][0]] > dep[d[i][1]]) swap(d[i][0], d[i][1]); update(1, 1, z, w[d[i][1]], d[i][2]); }}inline void read(){ ch[0] = ' '; while (ch[0] < 'C' || ch[0] > 'Q') scanf("%s", &ch);}void work(){ for (read(); ch[0] != 'D'; read()) { scanf("%d%d", &a, &b); if (ch[0] == 'Q') printf("%d\n", find(a, b)); else update(1, 1, z, w[d[a][1]], b); }}int main(){ for (scanf("%d", &zzz); zzz > 0; zzz--) { init(); work(); } return 0;}
0 0
- 专题总结:树链剖分入门介绍
- SG专题:博弈专题总结
- Ehcache学习总结(1)--Ehcache入门介绍
- JDBC专题介绍
- JDBC专题介绍
- JDBC专题介绍(zz)
- 线段树专题介绍
- HBase专题介绍 1
- HBase专题介绍 2
- HBase专题介绍 3
- HBase专题介绍 4
- HBase专题介绍 5
- HBase专题介绍6
- HBase专题介绍 1
- HBase专题介绍 2
- HBase专题介绍 3
- HBase专题介绍 4
- HBase专题介绍 5
- mvc
- spring securigy 初学问题记录
- 遗传算法的理解
- Hibernate映射文件总结
- Redis介绍
- 专题总结:树链剖分入门介绍
- javascript DOM
- 如何在Ubuntu上安装C/C++-Eclipse,及JDK安装,环境变量设置
- Java 8中处理日期和时间
- 谷歌推Android Studio 让开发应用更简单
- volatile变量修饰符—意料之外的问题(含代码)
- 修改Client Feature的图标
- linux线程的退出--附:一个变量,两个精彩
- 前端在线工具网址