poj 2763 Housewife Wind
来源:互联网 发布:hd网络是什么意思啊 编辑:程序博客网 时间:2024/05/19 02:39
Problem
poj.org/problem?id=2763
vjudge.net/contest/28982#problem/B
Reference
poj2763(树链剖分 - 边权)
Meaning
一棵 n 个点的树,每条边都有一个边权。一个人开始在 s 结点。两种操作:
0 u
:询问人从 s 走到 u 要走多久,之后人就走到了 u 这个点(即 s 更新为 u)1 i w
:把第 i 条边的权值改成 w
Analysis
考虑树链剖分。权值是在边上,要把权值“转移”到点上。
策略是:对于每一条边 e 的两个端点 f 和 t,如果 depth[f] > depth[t],就把边权记到 f 上,否则记到 t 上(即把边权转移到深度更大的端点处)。
Code
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = 100000;int head[N+1], from[N<<1], to[N<<1], nxt[N<<1], w[N<<1];void add_edge(int f, int t, int c, int sz){ from[sz] = f; to[sz] = t; w[sz] = c; nxt[sz] = head[f]; head[f] = sz;}int dep[N+1], fa[N+1], son[N+1], tsz[N+1];int tid[N+1], pos[N+1], top[N+1], tm;void heavy_light(int v, int f, int d){ dep[v] = d; fa[v] = f; tsz[v] = 1; son[v] = -1; for(int i = head[v]; ~i; i = nxt[i]) if(to[i] != f) { heavy_light(to[i], v, d + 1); tsz[v] += tsz[to[i]]; if(son[v] == -1 || tsz[to[i]] > tsz[son[v]]) son[v] = to[i]; }}void decompose(int v, int t){ top[v] = t; pos[v] = ++tm; tid[pos[v]] = v; if(son[v] == -1) return; decompose(son[v], t); for(int i = head[v]; ~i; i = nxt[i]) if(to[i] != fa[v] && to[i] != son[v]) decompose(to[i], to[i]);}int tree[N+1<<2];inline void pushup(int x){ tree[x] = tree[x<<1] + tree[x<<1|1];}void update(int p, int v, int l, int r, int rt){ if(l == r) { tree[rt] = v; return; } int m = l + r >> 1; if(p > m) update(p, v, m+1, r, rt<<1|1); else update(p, v, l, m, rt<<1); pushup(rt);}int sum(int ql, int qr, int l, int r, int rt){ if(ql <= l && r <= qr) return tree[rt]; if(qr < l || r < ql) return 0; int m = l + r >> 1; return sum(ql, qr, l, m, rt<<1) + sum(ql, qr, m+1, r, rt<<1|1);}int query(int l, int r, int n){ int ans = 0; while(top[l] != top[r]) { if(dep[top[l]] < dep[top[r]]) swap(l, r); ans += sum(pos[top[l]], pos[l], 1, n, 1); l = fa[top[l]]; } if(l != r) // 必须要这个判断 { if(dep[l] > dep[r]) swap(l, r); // 当处于同一条链 // 上面的那端要往下退一个点 -> son[l] // 因为 l 点记得权值是它上面那条边的 // 而那条边不在查询路径上 ans += sum(pos[son[l]], pos[r], 1, n, 1); } return ans;}int a[N+1] = {0}; // 结点 i 的初始权值int mp[N]; // 第 i 条边的权值记载 mp[i] 结点上void build(int l, int r, int rt){ if(l == r) { tree[rt] = a[tid[l]]; return; } int m = l + r >> 1; build(l, m, rt<<1); build(m+1, r, rt<<1|1); pushup(rt);}int main(){ int n, q, s; scanf("%d%d%d", &n, &q, &s); memset(head, ~0, sizeof head); for(int i = 1, f, t, c, sz = 0; i < n; ++i) { scanf("%d%d%d", &f, &t, &c); add_edge(f, t, c, sz++); add_edge(t, f, c, sz++); } heavy_light(1, 0, 1); tm = 0; decompose(1, 1); // 对每一条边,都映射到它深度更大的那个端点 // 并把它的权值记载那个映射点上 for(int i = 1, j = 0; i < n; ++i, j += 2) if(dep[from[j]] > dep[to[j]]) a[mp[i] = from[j]] = w[j]; else a[mp[i] = to[j]] = w[j]; build(1, n, 1); for(int op, v, e; q--; ) { scanf("%d", &op); if(op == 0) { scanf("%d", &v); printf("%d\n", query(s, v, n)); s = v; } else { scanf("%d%d", &e, &v); // 更新边就变成更新点 // mp[e] 找到要更新的点 update(pos[mp[e]], v, 1, n, 1); } } return 0;}
阅读全文
0 0
- POJ 2763 Housewife Wind
- POJ 2763 Housewife Wind
- poj 2763 Housewife Wind
- POJ 2763 Housewife Wind
- POJ 2763 Housewife Wind
- poj 2763 Housewife Wind
- POJ 2763 Housewife Wind
- POJ 2763 Housewife Wind
- POJ 2763 Housewife Wind
- poj 2763 Housewife Wind
- poj 2763 Housewife Wind(树链剖分)
- POJ 2763 Housewife Wind 树链剖分
- POJ 2763 Housewife Wind 树链剖分
- poj 2763 Housewife Wind(树链剖分)
- poj 2763 Housewife Wind 树链剖分
- POJ 2763 Housewife Wind (树链剖分)
- Housewife Wind - POJ 2763 树链刨分
- POJ 2763 Housewife Wind 树链剖分
- C#数组 -- 将数组的元素按照自己的意愿进行剔除。
- 2017.9.22 middle 失败总结
- 算法——归并排序
- String的几种比较方法对比(Compare,CompareTo, CompareOrdinal、Equals)
- Android Studio删除行快捷键
- poj 2763 Housewife Wind
- Win10 一些常用快捷键
- leetcode-Can Place Flowers
- NGUI2D3D屏幕适应
- hbase 将查询结果写入文件
- 数字再排序数组中出现的次数
- lua基础知识整理
- 计算机启动相关术语、问题
- POJ 3069 Saruman's Army