【POJ3237】【树链剖分】Tree
Description
You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions can be one of the following forms:
CHANGE i v |
Change the weight of the ith edge to v |
NEGATE a b |
Negate the weight of every edge on the path from a to b |
QUERY a b |
Find the maximum weight of edges on the path from a to b |
Input
The input contains multiple test cases. The first line of input contains an integer t (t ≤ 20), the number of test cases. Then follow the test cases.
Each test case is preceded by an empty line. The first nonempty line of its contains N (N ≤ 10,000). The next N − 1 lines each contains three integers a, b and c, describing an edge connecting nodes a and b with weight c. The edges are numbered in the order they appear in the input. Below them are the instructions, each sticking to the specification above. A lines with the word “DONE
” ends the test case.
Output
For each “QUERY
” instruction, output the result on a separate line.
Sample Input
1 3 1 2 1 2 3 2 QUERY 1 2 CHANGE 1 3 QUERY 1 2 DONE
Sample Output
1 3
Source
1 /* 2 宋代苏轼 3 《南乡子·重九涵辉楼呈徐君猷》 4 霜降水痕收。浅碧鳞鳞露远洲。酒力渐消风力软,飕飕。破帽多情却恋头。 5 佳节若为酬。但把清尊断送秋。万事到头都是梦,休休。明日黄花蝶也愁。 6 */ 7 #include <iostream> 8 #include <cstdio> 9 #include <algorithm> 10 #include <cstring> 11 #include <vector> 12 #include <utility> 13 #include <iomanip> 14 #include <string> 15 #include <cmath> 16 #include <queue> 17 #include <assert.h> 18 #include <map> 19 #include <ctime> 20 #include <cstdlib> 21 #include <stack> 22 #define LOCAL 23 const int INF = 0x3f3f3f3f; 24 const int maxn=100000 + 10; 25 const int maxnode = 100000; 26 const int maxm=100000 * 2 + 10; 27 using namespace std; 28 struct Node{//权值线段树 29 int l, r; 30 int Max, Min; 31 bool neg;//取反标记 32 }tree[maxn * 4]; 33 struct Edge{ 34 int u, v, w; 35 }edges[maxn];//输入的边 36 37 int n, fa[maxn], size[maxn]; 38 int son[maxn], dep[maxn], top[maxn]; 39 int pos[maxn], Time; 40 int M, head[maxn], next[maxm], to[maxm], w[maxm]; 41 42 //第一次dfs 43 void dfs_1(int u){ 44 size[u] = 1; 45 son[u] = 0; 46 for (int i = head[u]; i != -1; i = next[i]){ 47 int v = to[i]; 48 if (v == fa[u]) continue; 49 dep[v] = dep[u] + 1; 50 fa[v] = u; 51 dfs_1(v); 52 size[u] += size[v]; 53 if (size[v] > size[son[u]]) son[u] = v; 54 } 55 return; 56 } 57 void dfs_2(int u, int top_node){ 58 top[u] = top_node; 59 pos[u] = ++Time;//给他和他的父亲的边在线段树中的位置 60 //重边 61 if (son[u]) dfs_2(son[u], top_node); 62 //轻边 63 for (int i = head[u]; i != -1; i = next[i]){ 64 int v = to[i]; 65 if (v == fa[u] || v == son[u]) continue; 66 dfs_2(v, v); 67 } 68 } 69 //建树 70 void build(int x, int l, int r){ 71 tree[x].l = l;tree[x].r = r; 72 tree[x].Max = -INF; 73 tree[x].Min = INF; 74 tree[x].neg = 0; 75 if (l == r) return; 76 77 int mid = (l + r) >> 1; 78 build(x << 1, l, mid); 79 build((x << 1) | 1, mid + 1, r); 80 } 81 void update(int x){ 82 tree[x].Max = max(tree[x << 1].Max, tree[(x << 1) | 1].Max); 83 tree[x].Min = min(tree[x << 1].Min, tree[(x << 1) | 1].Min); 84 return; 85 } 86 //标记下传 87 void pushdown(int x){ 88 if (tree[x].l == tree[x].r) return; 89 90 if (tree[x].neg){ 91 int l = (x << 1), r = l | 1; 92 tree[l].neg ^= 1; 93 tree[l].Min *= -1; 94 tree[l].Max *= -1; 95 swap(tree[l].Min, tree[l].Max); 96 97 tree[r].neg ^= 1; 98 tree[r].Min *= -1; 99 tree[r].Max *= -1; 100 swap(tree[r].Min, tree[r].Max); 101 102 tree[x].neg = 0; 103 } 104 } 105 //在线段树中修改l,r为val 106 void change2(int x, int l, int r, int val){ 107 pushdown(x); 108 if (tree[x].l == l && tree[x].r == r){ 109 if (val == INF){//取反操作,注意已经pushdown过了 110 tree[x].neg = 1; 111 tree[x].Min *= -1; 112 tree[x].Max *= -1; 113 swap(tree[x].Min, tree[x].Max); 114 } else tree[x].Min = tree[x].Max = val;//更新val 115 return; 116 } 117 118 int mid = (tree[x].l + tree[x].r) >> 1; 119 if (r <= mid) change2(x << 1, l, r, val); 120 else if (l > mid) change2((x << 1) | 1, l, r, val); 121 else{ 122 change2(x << 1, l, mid, val); 123 change2((x << 1) | 1, mid + 1, r, val); 124 } 125 update(x); 126 } 127 int query2(int x, int l, int r){ 128 pushdown(x); 129 if (tree[x].l == l && tree[x].r == r) return tree[x].Max; 130 131 int mid = (tree[x].l + tree[x].r) >> 1; 132 if (r <= mid) return query2(x << 1, l, r); 133 else if (l > mid) return query2((x << 1) | 1, l, r); 134 else return max(query2((x << 1), l, mid), query2((x << 1) | 1, mid + 1, r)); 135 } 136 //树链剖分部分 137 void change(int x, int y, int v){ 138 while (top[x] != top[y]){ 139 //总是矮的往上爬.. 140 //保证dep[top[x]] >= dep[top[y]] 141 if (dep[top[x]] < dep[top[y]]) swap(x, y); 142 143 change2(1, pos[top[x]], pos[x], v); 144 x = fa[top[x]]; 145 } 146 147 if (x == y) return; 148 if (dep[x] > dep[y]) swap(x, y); 149 change2(1, pos[son[x]], pos[y], v); 150 } 151 int query(int x, int y){ 152 int Ans = -INF; 153 while (top[x] != top[y]){ 154 if (dep[top[x]] < dep[top[y]]) swap(x, y); 155 156 Ans = max(Ans, query2(1, pos[top[x]], pos[x])); 157 x = fa[top[x]]; 158 } 159 if (x == y) return Ans; 160 if (dep[x] > dep[y]) swap(x, y); 161 Ans = max(Ans, query2(1, pos[son[x]], pos[y])); 162 return Ans == -INF ? 0 : Ans; 163 } 164 void work(){ 165 while(1){ 166 char str[20]; 167 scanf("%s", str); 168 if(str[0] == 'C'){ 169 int x, v; 170 scanf("%d%d", &x, &v); 171 change2(1, pos[edges[x].v], pos[edges[x].v], v); 172 }else if(str[0] == 'N'){ 173 int l, r; 174 scanf("%d%d", &l, &r); 175 change(l, r, INF); 176 }else if(str[0] == 'Q'){//询问两点之间最大值 177 int l, r; 178 scanf("%d%d", &l, &r); 179 printf("%d\n", query(l, r)); 180 }else break; 181 } 182 } 183 //加边 184 void addEdge(int u, int v, int c){ 185 to[M] = v; 186 w[M] = c; 187 next[M] = head[u]; 188 head[u] = M++; 189 } 190 void init(){ 191 memset(head, -1, sizeof(head));//邻接表初始化 192 memset(dep, 0, sizeof(dep)); 193 M = Time = 0;//总边数和时间 194 fa[1] = size[0] = 0; 195 //加边 196 scanf("%d", &n); 197 for (int i = 1; i < n; i++){ 198 scanf("%d%d%d", &edges[i].u, &edges[i].v, &edges[i].w); 199 addEdge(edges[i].u, edges[i].v, edges[i].w); 200 addEdge(edges[i].v, edges[i].u, edges[i].w); 201 } 202 dfs_1(1); 203 dfs_2(1, 1); 204 build(1, 1, Time); 205 for (int i = 1; i < n; i++){ 206 int x = edges[i].u, y = edges[i].v; 207 //判断父亲 208 if (dep[x] > dep[y]) swap(edges[i].u, edges[i].v); 209 //u一定是父亲 210 change2(1, pos[edges[i].v], pos[edges[i].v], edges[i].w); 211 } 212 } 213 214 int main(){ 215 int T; 216 217 scanf("%d", &T); 218 while (T--){ 219 init(); 220 work(); 221 } 222 //printf("%d\n", INF); 223 return 0; 224 }