[HDU] 3966 树状数组+启发式树链剖分
2017-09-30 22:30
274 查看
树状数组+启发式树链剖分
一个讲解ppt
https://wenku.baidu.com/view/a088de01eff9aef8941e06c3.html
例题:Aragorn’s Story
点权树+路经加减+单点询问
时间复杂度 O(n+n+nlogn+Qlogn)
空间复杂度 O(n)
一个讲解ppt
https://wenku.baidu.com/view/a088de01eff9aef8941e06c3.html
例题:Aragorn’s Story
点权树+路经加减+单点询问
时间复杂度 O(n+n+nlogn+Qlogn)
空间复杂度 O(n)
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int MAXN = (int)5e5 + 5; struct Edge{int to, next;} E[MAXN<<1]; 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; int N, M, P; void add_edge(int u, int v) { E[tot].to = v; E[tot].next = head[u]; head[u] = tot++; } void dfs_1(int u, int u_fa, int u_deep) { deep[u] = u_deep; fa[u] = u_fa; num[u] = 1; for(int i = head[u]; ~i; i = E[i].next) { int &v = E[i].to; if(v == u_fa) continue; dfs_1(v, u, u_deep + 1); num[u] += num[v]; if(son[u] == -1 || num[v] > num[son[v]]) { son[u] = v; } } } int c[MAXN], val[MAXN]; int sum(int i) { int res = 0; while(i > 0) { res += c[i]; i -= i&(-i); } return res; } void add(int i, int val) { while(i <= N) { c[i] += val; i += i&(-i); } } 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; i = E[i].next) { int &v = E[i].to; if(v != son[u] && v != fa[u]) { getpos(v, v); } } } void change(int u, int v, int _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); } int main() { while(scanf("%d%d%d", &N, &M, &P) != EOF) { memset(head, 0xff, sizeof head); memset(son , 0xff, sizeof son ); memset(c , 0x00, sizeof c ); tot = 0; pos = 1; for(int i = 1; i <= N; ++i) { scanf("%d", val + i); } for(int i = 0; i < M; ++i) { int x, y; scanf("%d%d", &x, &y); add_edge(x, y); add_edge(y, x); } dfs_1(1, 0, 0); getpos(1, 1); for(int i = 1; i <= N; ++i) { add(p[i], val[i]); add(p[i] + 1, -val[i]); } while(P--) { char op; scanf("\n%c", &op); if(op == 'Q') { int x; scanf("%d", &x); printf("%d\n", sum(p[x])); } else { int x, y, c; scanf("%d%d%d", &x, &y, &c); if(op == 'D') c = -c; change(x, y, c); } } } return 0; }
相关文章推荐
- hdu 3966 Aragorn's Story 树链剖分
- Hdu 3966 Aragorn's Story (树链剖分 + 线段树区间更新)
- HDU 3966 Aragorn's Story (树链剖分)
- 【HDU】3966 Aragorn's Story 树链剖分
- HDU 3966 Aragorn's Story (树链剖分 区间更新,点查询)
- hdu 3966 树链剖分第3遍
- HDU 3966 基础树链剖分
- hdu 3966 树链剖分+线段树
- HDU 3966 Aragorn's Story 树链剖分
- HDU-3966-Aragorn's Story(树链剖分)
- HDU 3966 树链剖分学习
- 树链剖分+数据结构维护 Hdu 3966 Aragorn's Story 题解
- HDU 3966 树链剖分
- HDU 3966 树链剖分
- hdu 3966 树链剖分
- HDU 3966 Aragorn's Story 树链剖分
- hdu 3966 Aragorn's Story 树链剖分
- hdu 3966( 树链剖分+点权更新)
- hdu 3966 Aragorn's Story 树链剖分
- HDU 3966 Aragorn's Story(树链剖分)