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
", 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 }
原文地址:https://www.cnblogs.com/fightfordream/p/5941779.html