题目链接:
题目描述:
给出一个树,每个节点都有一个权值,有三种操作:
1:( I, i, j, x ) 从i到j的路径上经过的节点全部都加上x;
2:( D, i, j, x ) 从i到j的路径上经过的节点全部都减去x;
3:(Q, x) 查询节点x的权值为多少?
解题思路:
可以用树链剖分对节点进行hash,然后用线段树维护(修改,查询),数据范围比较大,要对线段树进行区间更新
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 7 const int maxn = 50010; 8 #define lson(x) 2*x+1 9 #define rson(x) 2*x+2 10 11 struct e 12 { 13 int to, next; 14 }edge[maxn*2]; 15 struct node 16 { 17 int l, r, val, x; 18 int Mid () 19 { 20 return (l+r)/2; 21 } 22 }tree[maxn*4]; 23 int val[maxn], x[maxn], deep[maxn], size[maxn], tot, num; 24 int son[maxn], top[maxn], id[maxn], head[maxn], fa[maxn]; 25 26 void init () 27 { 28 num = tot =0; 29 memset (head, -1, sizeof(head)); 30 } 31 32 void Add (int from, int to) 33 { 34 edge[tot].to = to; 35 edge[tot].next = head[from]; 36 head[from] = tot ++; 37 } 38 39 //找重边 40 void dfs1 (int u, int f, int dep) 41 { 42 son[u] = 0; 43 fa[u] = f; 44 deep[u] = dep; 45 size[u] = 1; 46 47 for (int i=head[u]; i!=-1; i=edge[i].next) 48 { 49 int v = edge[i].to; 50 if (v == f) continue; 51 dfs1 (v, u, dep+1); 52 size[u] += size[v]; 53 if (size[son[u]] < size[v]) 54 son[u] = v; 55 } 56 } 57 58 //重边连接成重链 59 void dfs2 (int u, int tp) 60 { 61 top[u] = tp; 62 id[u] = ++num; 63 if (son[u]) dfs2 (son[u], tp); 64 65 for (int i=head[u]; i!=-1; i=edge[i].next) 66 { 67 int v = edge[i].to; 68 if (v == fa[u] || v == son[u]) continue; 69 dfs2 (v, v); 70 } 71 } 72 73 //区间更新线段树,向下一层更新 74 void pushup (int x) 75 { 76 tree[lson(x)].x += tree[x].x; 77 tree[rson(x)].x += tree[x].x; 78 tree[lson(x)].val += tree[x].x; 79 tree[rson(x)].val += tree[x].x; 80 tree[x].x = 0; 81 } 82 83 void build (int root, int l, int r) 84 { 85 tree[root].l = l; 86 tree[root].r = r; 87 tree[root].x = tree[root].val = 0; 88 89 if (l == r) 90 { 91 tree[root].val = val[l]; 92 return ; 93 } 94 95 build (lson(root), l, tree[root].Mid()); 96 build (rson(root), tree[root].Mid()+1, r); 97 } 98 99 void updata (int root, int l, int r, int x) 100 { 101 if (tree[root].l == l && r == tree[root].r) 102 { 103 tree[root].val += x; 104 tree[root].x += x; 105 return ; 106 } 107 108 if (tree[root].x) 109 pushup (root); 110 111 if (r <= tree[root].Mid()) 112 updata (lson(root), l, r, x); 113 else if (tree[root].Mid() < l) 114 updata (rson(root), l, r, x); 115 else 116 { 117 updata (lson(root), l, tree[root].Mid(), x); 118 updata (rson(root), tree[root].Mid()+1, r, x); 119 } 120 } 121 122 int query (int root, int x) 123 { 124 if (tree[root].l == tree[root].r && tree[root].l == x) 125 return tree[root].val; 126 127 if (tree[root].x) 128 pushup (root); 129 130 if (x <= tree[root].Mid()) 131 query (lson(root), x); 132 else 133 query (rson(root), x); 134 } 135 136 //处理节点u,v 137 void alter (int u, int v,int x) 138 { 139 int tp1 = top [u]; 140 int tp2 = top [v]; 141 142 while (tp1 != tp2) 143 {//两个节点不在同一个重链上 144 if (deep[tp1] < deep[tp2]) 145 { 146 swap (tp1, tp2); 147 swap (u, v); 148 }//deep深的重链上升 149 150 updata (0, id[tp1], id[u], x); 151 u = fa[tp1]; 152 tp1 = top[u]; 153 } 154 155 //在同一条重链上 156 if (deep[u] > deep[v]) 157 swap (u, v); 158 updata (0, id[u], id[v], x); 159 160 } 161 162 int main () 163 { 164 int n, m, q; 165 166 while (scanf ("%d %d %d", &n, &m, &q) != EOF) 167 { 168 init (); 169 for (int i=1; i<=n; i++) 170 scanf ("%d", &x[i]); 171 for (int i=0; i<m; i++) 172 { 173 int x, y; 174 scanf ("%d %d", &x, &y); 175 Add (x, y); 176 Add (y, x); 177 } 178 179 dfs1 (1, 0, 1); 180 dfs2 (1, 1); 181 182 //hash原来节点 183 for (int i=1; i<=n; i++) 184 val[id[i]] = x[i]; 185 build (0, 1, n); 186 187 while (q --) 188 { 189 char str[10]; 190 int l, r, x; 191 scanf ("%s", str); 192 193 if (str[0] == 'Q') 194 { 195 scanf ("%d", &x); 196 printf ("%d ", query (0, id[x])); 197 } 198 else if (str[0] == 'I') 199 { 200 scanf ("%d %d %d", &l, &r, &x); 201 alter (l, r, x); 202 } 203 else 204 { 205 scanf ("%d %d %d", &l, &r, &x); 206 alter (l, r, -x); 207 } 208 209 } 210 } 211 return 0; 212 }