HDU 3966:Aragorn's Story(树链剖分)
http://acm.hdu.edu.cn/showproblem.php?pid=3966
题意:有n个点n-1条边,每个点有一个权值,有两种操作:询问一个点上权值是多少和修改u到v这条链上的权值。
思路:树链剖分。学习地址:http://blog.sina.com.cn/s/blog_7a1746820100wp67.html http://blog.csdn.net/acdreamers/article/details/10591443
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <string> 7 #include <iostream> 8 #include <stack> 9 #include <map> 10 #include <queue> 11 using namespace std; 12 #define N 50010 13 #define INF 0x3f3f3f3f 14 #define lson rt<<1, l, m 15 #define rson rt<<1|1, m+1, r 16 struct node 17 { 18 int u, v, next; 19 }edge[N*2]; 20 int tot, head[N]; //存边部分 21 int tim, son[N], tid[N], fa[N], depth[N], size[N], top[N], num[N], rak[N]; //树剖部分 22 //分别对应DFS的时间、重儿子、节点的时间戳、父节点、节点深度、该节点的子树的节点数、树链中的头节点、初始节点权值、rak[i]表示时间戳为i的节点是rak[i](在线段树中的位置) 23 int tree[N<<2], col[N<<2]; //线段树部分 24 int n; 25 26 void init() 27 { 28 tim = tot = 0; 29 memset(head, -1, sizeof(head)); 30 memset(son, -1, sizeof(son)); 31 } 32 33 void add(int u, int v) 34 { 35 edge[tot].next = head[u]; edge[tot].u = u; edge[tot].v = v; head[u] = tot++; 36 } 37 38 void dfs1(int u, int f, int d) 39 { 40 size[u] = 1; 41 depth[u] = d; 42 fa[u] = f; 43 for(int i = head[u]; ~i; i = edge[i].next) { 44 int v = edge[i].v; 45 if(f == v) continue; 46 dfs1(v, u, d + 1); 47 if(size[v] > size[son[u]] || son[u] == -1) son[u] = v; 48 size[u] += size[v]; 49 } 50 } 51 52 void dfs2(int u, int f) 53 { 54 top[u] = f; 55 tid[u] = ++tim; 56 rak[tid[u]] = u; 57 if(son[u] == -1) return ; 58 dfs2(son[u], f); //是重儿子的话 59 for(int i = head[u]; ~i; i = edge[i].next) { 60 int v = edge[i].v; 61 if(v != son[u] && v != fa[u]) dfs2(v, v); //不是重儿子的话 62 } 63 } 64 65 void PushDown(int rt, int len) 66 { 67 if(col[rt]) { 68 col[rt<<1] += col[rt]; 69 col[rt<<1|1] += col[rt]; 70 tree[rt<<1] += (len - (len >> 1)) * col[rt]; 71 tree[rt<<1|1] += (len >> 1) * col[rt]; 72 col[rt] = 0; 73 } 74 } 75 76 void Build(int rt, int l, int r) 77 { 78 col[rt] = 0; 79 tree[rt] = 0; 80 if(l == r) { 81 tree[rt] = num[rak[l]]; 82 return ; 83 } 84 int m = (l + r) >> 1; 85 Build(lson); 86 Build(rson); 87 } 88 89 void Update(int rt, int l, int r, int L, int R, int val) 90 { 91 if(L <= l && r <= R) { 92 col[rt] += val; 93 tree[rt] += val * (r - l + 1); 94 return ; 95 } 96 PushDown(rt, r - l + 1); 97 int m = (l + r) >> 1; 98 if(L <= m) Update(lson, L, R, val); 99 if(R > m) Update(rson, L, R, val); 100 } 101 102 int Query(int rt, int l, int r, int id) 103 { 104 if(l == r && l == id) return tree[rt]; 105 PushDown(rt, r - l + 1); 106 int m = (l + r) >> 1; 107 if(id <= m) return Query(lson, id); 108 else return Query(rson, id); 109 } 110 111 void Change(int u, int v, int val) 112 { 113 while(top[u] != top[v]) { 114 if(depth[top[u]] < depth[top[v]]) swap(u, v); 115 Update(1, 1, n, tid[top[u]], tid[u], val); //父节点编号小 116 u = fa[top[u]]; //!!! 117 } 118 if(depth[u] > depth[v]) swap(u, v); 119 Update(1, 1, n, tid[u], tid[v], val); 120 } 121 122 int main() 123 { 124 int m, q, id, u, v, val; 125 char s[2]; 126 while(~scanf("%d%d%d", &n, &m, &q)) { 127 init(); 128 for(int i = 1; i <= n; i++) scanf("%d", &num[i]); 129 for(int i = 0; i < m; i++) { 130 scanf("%d%d", &u, &v); 131 add(u, v); add(v, u); 132 } 133 dfs1(1, -1, 1 ); 134 dfs2(1, 1); 135 Build(1, 1, n); 136 while(q--) { 137 scanf("%s", s); 138 if(s[0] == 'Q') { 139 scanf("%d", &id); 140 printf("%d\n", Query(1, 1, n, tid[id])); 141 } else { 142 scanf("%d%d%d", &u, &v, &val); 143 if(s[0] == 'D') val = -val; 144 Change(u, v, val); 145 } 146 } 147 } 148 return 0; 149 }