HDU 3966 RE 树链剖分 线段树 Aragorn's Story
2015-08-06 13:56
190 查看
题意:
给出一棵树,每个顶点上有一个权值。
操作:选择一条路径,并将路径上所有的点的权值同时加或减某个数。
查询:某个点的当前权值
分析:
树链剖分完毕后,就是简单的线段树区间更新。
提交的时候注意要要加一句扩栈的代码,用C++提交。
代码君
给出一棵树,每个顶点上有一个权值。
操作:选择一条路径,并将路径上所有的点的权值同时加或减某个数。
查询:某个点的当前权值
分析:
树链剖分完毕后,就是简单的线段树区间更新。
提交的时候注意要要加一句扩栈的代码,用C++提交。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; void read(int& x) { x = 0; char c = ' '; while(c < '0' || c > '9') c = getchar(); while('0' <= c && c <= '9') { x = x * 10 + c - '0'; c = getchar(); } } const int maxn = 50000 + 10; const int maxnode = maxn * 4; struct Edge { int v, nxt; Edge() {} Edge(int v, int nxt) :v(v), nxt(nxt) {} }; int n, m, q; int a[maxn]; int ecnt, head[maxn]; Edge edges[maxn * 2]; void AddEdge(int u, int v) { edges[++ecnt] = Edge(v, head[u]); head[u] = ecnt; edges[++ecnt] = Edge(u, head[v]); head[v] = ecnt; } int dep[maxn], fa[maxn], son[maxn], sz[maxn]; int tot, id[maxn], pos[maxn], top[maxn]; void dfs(int u) { sz[u] = 1; son[u] = -1; for(int i = head[u]; i; i = edges[i].nxt) { int v = edges[i].v; if(v == fa[u]) continue; fa[v] = u; dep[v] = dep[u] + 1; dfs(v); sz[u] += sz[v]; if(son[u] == -1 || sz[v] > sz[son[u]]) son[u] = v; } } void dfs2(int u, int tp) { top[u] = tp; id[u] = ++tot; pos[tot] = u; if(son[u] == -1) return; if(son[u]) dfs2(son[u], tp); for(int i = head[u]; i; i = edges[i].nxt) { int v = edges[i].v; if(v == fa[u] || v == son[u]) continue; dfs2(v, v); } } int sumv[maxnode], addv[maxnode]; char cmd[10]; void pushup(int o) { sumv[o] = sumv[o<<1] + sumv[o<<1|1]; } void build(int o, int L, int R) { if(L == R) { sumv[o] = a[pos[L]]; return; } int M = (L + R) / 2; build(o<<1, L, M); build(o<<1|1, M+1, R); pushup(o); } void pushdown(int o, int L, int R) { if(addv[o]) { addv[o<<1] += addv[o]; addv[o<<1|1] += addv[o]; int M = (L + R) / 2; sumv[o<<1] += (M - L + 1) * addv[o]; sumv[o<<1|1] += (R - M) * addv[o]; addv[o] = 0; } } void update(int o, int L, int R, int qL, int qR, int v) { if(qL <= L && R <= qR) { sumv[o] += (R - L + 1) * v; addv[o] += v; return; } pushdown(o, L, R); int M = (L + R) / 2; if(qL <= M) update(o<<1, L, M, qL, qR, v); if(qR > M) update(o<<1|1, M+1, R, qL, qR, v); pushup(o); } void UPDATE(int u, int v, int val) { int t1 = top[u], t2 = top[v]; while(t1 != t2) { if(dep[t1] < dep[t2]) { swap(u, v); swap(t1, t2); } update(1, 1, n, id[t1], id[u], val); u = fa[t1]; t1 = top[u]; } if(dep[u] > dep[v]) swap(u, v); update(1, 1, n, id[u], id[v], val); } int query(int o, int L, int R, int p) { if(L == R) return sumv[o]; pushdown(o, L, R); int M = (L + R) / 2; if(p <= M) return query(o<<1, L, M, p); else return query(o<<1|1, M+1, R, p); } int main() { while(scanf("%d%d%d", &n, &m, &q) == 3) { for(int i = 1; i <= n; i++) read(a[i]); memset(head, 0, sizeof(head)); ecnt = 0; for(int i = 1; i < n; i++) { int u, v; read(u); read(v); AddEdge(u, v); } dfs(1); tot = 0; dfs2(1, 1); memset(addv, 0, sizeof(addv)); build(1, 1, n); while(q--) { scanf("%s", cmd); int u, v, d; read(u); if(cmd[0] == 'Q') { printf("%d\n", query(1, 1, n, id[u])); } else { read(v); read(d); if(cmd[0] == 'D') d = -d; UPDATE(u, v, d); } } } return 0; }
代码君
相关文章推荐
- Windows下配置Django环境
- 回溯算法(Backtracking)说明与实例
- 通过beego快速创建一个Restful风格API项目及API文档自动化
- go[x]agent在windows和ubuntu下的安装步骤
- 如何在Django中正确的使用和设置Database和Model
- 【Mongo】数据备份与还原
- HDU1056 Hangover
- 南邮 OJ 1459 Getting a good bonus!
- django1.4日志模块配置及使用
- Drawing with GoogLeNet
- golang 1.5 预计 8 月11 日发布
- Django跑起来
- django step by step
- Category支持添加属性与成员变量
- Golomb 编码
- Algorithms(一)---最大子数组和问题
- go项目make
- algorithm中的next_permutation函数
- POJ 1389 Area of Simple Polygons(扫描线)
- 使用Paragon Partition Manager调整磁盘大小