树链剖分
来源:互联网 发布:js怎么取整数 编辑:程序博客网 时间:2024/05/16 13:06
ACM模版
点权
参考题目链接:
HDU 3966 Aragorn’s Story
/* * 基于点权,查询单点值,修改路径的上的点权 */const int MAXN = 50010;struct Edge{ int to, next;} edge[MAXN * 2];int head[MAXN], tot;int top[MAXN]; // top[v]表示v所在的重链的顶端节点int fa[MAXN]; // 父亲节点int deep[MAXN]; // 深度int num[MAXN]; // num[v]表示以v为根的子树的节点数int p[MAXN]; // p[v]表示v对应的位置int fp[MAXN]; // fp和p数组相反int son[MAXN]; // 重儿子int pos;void init(){ tot = 0; memset(head, -1, sizeof(head)); pos = 1; // 使用树状数组,编号从头1开始 memset(son, -1, sizeof(son)); return ;}void addedge(int u, int v){ edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++; return ;}void dfs1(int u, int pre, int d){ deep[u] = d; fa[u] = pre; num[u] = 1; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (v != pre) { dfs1(v, u, d + 1); num[u] += num[v]; if (son[u] == -1 || num[v] > num[son[u]]) { son[u] = v; } } } return ;}void getpos(int u, int sp){ top[u] = sp; p[u] = pos++; fp[p[u]] = u; if (son[u] == -1) { return ; } getpos(son[u], sp); for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (v != son[u] && v != fa[u]) { getpos(v, v); } } return ;}//树状数组int lowbit(int x){ return x & (-x);}int c[MAXN];int n;int sum(int i){ int s = 0; while (i > 0) { s += c[i]; i -= lowbit(i); } return s;}void add(int i, int val){ while (i <= n) { c[i] += val; i += lowbit(i); } return ;}void Change(int u, int v, int val) // u->v的路径上点的值改变val{ int f1 = top[u], f2 = top[v]; while (f1 != f2) { if (deep[f1] < deep[f2]) { swap(f1, f2); swap(u, v); } add(p[f1], val); add(p[u] + 1, -val); u = fa[f1]; f1 = top[u]; } if (deep[u] > deep[v]) { swap(u, v); } add(p[u], val); add(p[v] + 1, -val); return ;}int a[MAXN];int main(){ int M, P; while (scanf("%d%d%d", &n, &M, &P) == 3) { int u, v; int C1, C2, K; char op[10]; init(); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); } while(M--) { scanf("%d%d", &u, &v); addedge(u, v); addedge(v, u); } dfs1(1, 0, 0); getpos(1, 1); memset(c, 0, sizeof(c)); for (int i = 1; i <= n; i++) { add(p[i],a[i]); add(p[i] + 1, -a[i]); } while (P--) { scanf("%s", op); if (op[0] == 'Q') { scanf("%d", &u); printf("%d\n", sum(p[u])); } else { scanf("%d%d%d", &C1, &C2, &K); if (op[0] == 'D') { K = -K; } Change(C1, C2, K); } } } return 0;}
边权
/* * 基于边权,修改单条边权,查询路径边权最大值 */const int MAXN = 10010;struct Edge{ int to, next;} edge[MAXN * 2];int head[MAXN], tot;int top[MAXN]; // top[v]表示v所在的重链的顶端节点int fa[MAXN]; // 父亲节点int deep[MAXN]; // 深度int num[MAXN]; // num[v]表示以v为根的子树的节点数int p[MAXN]; // p[v]表示v与其父亲节点的连边在线段树中的位置int fp[MAXN]; // 和p数组相反int son[MAXN]; // 重儿子int pos;void init(){ tot = 0; memset(head, -1, sizeof(head)); pos = 0; memset(son, -1, sizeof(son)); return ;}void addedge(int u, int v){ edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++; return ;}void dfs1(int u, int pre, int d) // 第一遍dfs求出fa,deep,num,son{ deep[u] = d; fa[u] = pre; num[u] = 1; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (v != pre) { dfs1(v, u, d + 1); num[u] += num[v]; if (son[u] == -1 || num[v] > num[son[u]]) { son[u] = v; } } }}void getpos(int u,int sp) // 第二遍dfs求出top和p{ top[u] = sp; p[u] = pos++; fp[p[u]] = u; if (son[u] == -1) { return ; } getpos(son[u], sp); for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (v != son[u] && v != fa[u]) { getpos(v,v); } } return ;}// 线段树struct Node{ int l, r; int Max;} segTree[MAXN * 3];void build(int i, int l, int r){ segTree[i].l = l; segTree[i].r = r; segTree[i].Max = 0; if (l == r) { return ; } int mid = (l + r) / 2; build(i << 1, l, mid); build((i << 1) | 1, mid + 1, r); return ;}void push_up(int i){ segTree[i].Max = max(segTree[i << 1].Max, segTree[(i << 1)|1].Max);}void update(int i, int k, int val) // 更新线段树的第k个值为val{ if (segTree[i].l == k && segTree[i].r == k) { segTree[i].Max = val; return ; } int mid = (segTree[i].l + segTree[i].r) / 2; if (k <= mid) { update(i << 1, k, val); } else { update((i << 1) | 1, k, val); } push_up(i); return ;}int query(int i, int l, int r) // 查询线段树中[l,r]的最大值{ if (segTree[i].l == l && segTree[i].r == r) { return segTree[i].Max; } int mid = (segTree[i].l + segTree[i].r) / 2; if (r <= mid) { return query(i << 1, l, r); } else if (l > mid) { return query((i << 1) | 1, l, r); } else { return max(query(i << 1, l, mid), query((i << 1) | 1, mid + 1, r)); }}int find(int u,int v) // 查询u->v边的最大值{ int f1 = top[u], f2 = top[v]; int tmp = 0; while (f1 != f2) { if (deep[f1] < deep[f2]) { swap(f1, f2); swap(u, v); } tmp = max(tmp, query(1, p[f1], p[u])); u = fa[f1]; f1 = top[u]; } if (u == v) { return tmp; } if (deep[u] > deep[v]) { swap(u, v); } return max(tmp, query(1, p[son[u]], p[v]));}int e[MAXN][3];int main(){ // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); int T; int n; scanf("%d", &T); while (T--) { init(); scanf("%d", &n); for (int i = 0; i < n - 1; i++) { scanf("%d%d%d", &e[i][0], &e[i][1], &e[i][2]); addedge(e[i][0], e[i][1]); addedge(e[i][1], e[i][0]); } dfs1(1, 0, 0); getpos(1, 1); build(1, 0, pos - 1); for (int i = 0; i < n-1; i++) { if (deep[e[i][0]] > deep[e[i][1]]) { swap(e[i][0],e[i][1]); } update(1, p[e[i][1]], e[i][2]); } char op[10]; int u, v; while (scanf("%s", op) == 1) { if (op[0] == 'D') { break; } scanf("%d%d", &u, &v); if (op[0] == 'Q') { printf("%d\n", find(u, v)); // 查询u->v路径上边权的最大值 } else { update(1, p[e[u - 1][1]], v); // 修改第u条边的长度为v } } } return 0;}
0 0
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 树链剖分
- 合并两个数值按升序的
- 文章标题
- tomcat 中文乱码
- 2016XTU算法专题个人赛1 题解
- AndroidStudio导入项目一直卡在Building gradle project info最快速解决方案
- 树链剖分
- malloc和free
- Picture hd 2052
- Java实现 二叉搜索树算法(BST)
- TypeError: 'stepUp' called on an object that does not implement interface HTMLInputElement
- 基于搜索引擎的新闻搜索的弊端及搜索优化需求设计
- 【数论】 再数17 容斥原理
- 约瑟夫问题之求喊到3的退出
- 一个界面使用两个tableView