POJ 3237:Tree(树链剖分)
http://poj.org/problem?id=3237
题意:树链剖分。操作有三种:改变一条边的边权,将 a 到 b 的每条边的边权都翻转(即 w[i] = -w[i]),询问 a 到 b 的最大边权。
思路:一开始没有用区间更新,每次翻转的时候都更新到叶子节点,居然也能过,后来看别人的发现也是可以区间更新的。
第一种:无区间更新水过
1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <string> 6 #include <cmath> 7 #include <queue> 8 #include <vector> 9 using namespace std; 10 #define N 100010 11 #define INF -0x7fffffff 12 #define lson rt<<1, l, m 13 #define rson rt<<1|1, m + 1, r 14 struct node 15 { 16 int v, w, next; 17 }edge[N*2]; 18 int top[N], size[N], dep[N], son[N], fa[N], tid[N], time; 19 int tot, head[N], e[N][3]; 20 int tree[N<<2]; 21 22 void init() 23 { 24 memset(head, -1, sizeof(head)); 25 memset(son, -1, sizeof(son)); 26 time = tot = 0; 27 } 28 29 void add(int u, int v, int w) 30 { 31 edge[tot].v = v; edge[tot].next = head[u]; edge[tot].w = w; head[u] = tot++; 32 } 33 34 void dfs1(int u, int f, int d) 35 { 36 size[u] = 1; 37 dep[u] = d; 38 fa[u] = f; 39 for(int i = head[u]; ~i; i = edge[i].next) { 40 int v = edge[i].v; 41 if(v == f) continue; 42 dfs1(v, u, d + 1); 43 size[u] += size[v]; 44 if(son[u] == -1 || size[son[u]] < size[v]) son[u] = v; 45 } 46 } 47 48 void dfs2(int u, int tp) 49 { 50 top[u] = tp; 51 tid[u] = ++time; 52 if(son[u] == -1) return ; 53 dfs2(son[u], tp); 54 for(int i = head[u]; ~i; i = edge[i].next) { 55 int v = edge[i].v; 56 if(v != son[u] && v != fa[u]) 57 dfs2(v, v); 58 } 59 } 60 61 void pushup(int rt) 62 { 63 tree[rt] = max(tree[rt<<1], tree[rt<<1|1]); 64 } 65 66 void build(int rt, int l, int r) 67 { 68 tree[rt] = 0; 69 if(l == r) return ; 70 int m = (l + r) >> 1; 71 build(lson); build(rson); 72 } 73 74 void update(int rt, int l, int r, int id, int w) // 更新边 75 { 76 if(l == r && l == id) { 77 tree[rt] = w; 78 return ; 79 } 80 if(l == r) return ; 81 int m = (l + r) >> 1; 82 if(id <= m) update(lson, id, w); 83 else update(rson, id, w); 84 pushup(rt); 85 } 86 87 void Update(int rt, int l, int r, int L, int R) // 翻转值 88 { 89 if(l == r && L <= l && r <= R) { 90 tree[rt] = -tree[rt]; 91 return ; 92 } 93 if(l == r) return ; 94 int m = (l + r) >> 1; 95 if(L <= m) Update(lson, L, R); 96 if(R > m) Update(rson, L, R); 97 pushup(rt); 98 } 99 100 int query(int rt, int l, int r, int L, int R) 101 { 102 int ans = INF; 103 if(L <= l && r <= R) { 104 ans = max(ans, tree[rt]); 105 return ans; 106 } 107 int m = (l + r) >> 1; 108 if(L <= m) ans = max(ans, query(lson, L, R)); 109 if(m < R) ans = max(ans, query(rson, L, R)); 110 return ans; 111 } 112 113 int change(int u, int v) // 查询 (u, v) 最长距离 114 { 115 int ans = INF; 116 while(top[u] != top[v]) { 117 if(dep[top[u]] < dep[top[v]]) swap(u, v); 118 ans = max(ans, query(1, 1, time, tid[top[u]], tid[u])); 119 u = fa[top[u]]; 120 } 121 if(u == v) return ans; 122 if(dep[u] > dep[v]) swap(u, v); 123 ans = max(ans, query(1, 1, time, tid[son[u]], tid[v])); 124 return ans; 125 } 126 127 void uuu(int u, int v) // 将值翻转 128 { 129 while(top[u] != top[v]) { 130 if(dep[top[u]] < dep[top[v]]) swap(u, v); 131 Update(1, 1, time, tid[top[u]], tid[u]); 132 u = fa[top[u]]; 133 } 134 if(u == v) return ; 135 if(dep[u] > dep[v]) swap(u, v); 136 Update(1, 1, time, tid[son[u]], tid[v]); 137 } 138 139 void debug() 140 { 141 printf("debug *************\n"); 142 printf("%d\n", time); 143 for(int i = 0; i <= time; i++) { 144 printf("%d, ", top[i]); 145 } 146 puts(""); 147 } 148 149 int main() 150 { 151 int t; 152 scanf("%d", &t); 153 while(t--) { 154 int n; 155 scanf("%d", &n); 156 init(); 157 for(int i = 1; i < n; i++) { 158 scanf("%d%d%d", &e[i][0], &e[i][1], &e[i][2]); 159 add(e[i][0], e[i][1], e[i][2]); 160 add(e[i][1], e[i][0], e[i][2]); 161 } 162 dfs1(1, 1, 1); 163 dfs2(1, 1); 164 build(1, 1, time); 165 for(int i = 1; i < n; i++) { 166 if(dep[e[i][0]] > dep[e[i][1]]) swap(e[i][0], e[i][1]); 167 update(1, 1, time, tid[e[i][1]], e[i][2]); 168 } 169 // for(int i = 1; i <= n; i++) printf("tid[%d] :%d\n", i, tid[i]); 170 char s[10]; 171 int a, b; 172 while(scanf("%s", s) == 1) { 173 if(s[0] == 'D') break; 174 scanf("%d%d", &a, &b); 175 if(s[0] == 'Q') { 176 // puts(""); 177 printf("%d\n", change(a, b)); 178 // puts(""); 179 } else if(s[0] == 'N') { 180 uuu(a, b); 181 } else { 182 update(1, 1, time, tid[e[a][1]], b); 183 } 184 } 185 } 186 return 0; 187 }
第二种:区间更新
比上一种快了一倍的时间。就是记录一个最大值和最小值,在翻转的时候,最大值 = -最小值, 最小值 = -最大值,每次标记取反。这样可以快速求出来。
1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <string> 6 #include <cmath> 7 #include <queue> 8 #include <vector> 9 using namespace std; 10 #define N 100010 11 #define INF 0x7fffffff 12 #define lson rt<<1, l, m 13 #define rson rt<<1|1, m + 1, r 14 struct node 15 { 16 int v, w, next; 17 }edge[N*2]; 18 int top[N], size[N], dep[N], son[N], fa[N], tid[N], time; 19 int tot, head[N], e[N][3]; 20 int col[N<<2], Min[N<<2], Max[N<<2]; 21 22 void init() 23 { 24 memset(head, -1, sizeof(head)); 25 memset(son, -1, sizeof(son)); 26 time = tot = 0; 27 } 28 29 void add(int u, int v, int w) 30 { 31 edge[tot].v = v; edge[tot].next = head[u]; edge[tot].w = w; head[u] = tot++; 32 } 33 34 void dfs1(int u, int f, int d) 35 { 36 size[u] = 1; 37 dep[u] = d; 38 fa[u] = f; 39 for(int i = head[u]; ~i; i = edge[i].next) { 40 int v = edge[i].v; 41 if(v == f) continue; 42 dfs1(v, u, d + 1); 43 size[u] += size[v]; 44 if(son[u] == -1 || size[son[u]] < size[v]) son[u] = v; 45 } 46 } 47 48 void dfs2(int u, int tp) 49 { 50 top[u] = tp; 51 tid[u] = ++time; 52 if(son[u] == -1) return ; 53 dfs2(son[u], tp); 54 for(int i = head[u]; ~i; i = edge[i].next) { 55 int v = edge[i].v; 56 if(v != son[u] && v != fa[u]) 57 dfs2(v, v); 58 } 59 } 60 61 void pushup(int rt) 62 { 63 Min[rt] = min(Min[rt<<1], Min[rt<<1|1]); 64 Max[rt] = max(Max[rt<<1], Max[rt<<1|1]); 65 } 66 67 void pushdown(int rt) 68 { 69 int tmp; 70 if(col[rt]) { 71 tmp = -Max[rt<<1]; 72 Max[rt<<1] = -Min[rt<<1]; 73 Min[rt<<1] = tmp; 74 75 tmp = -Max[rt<<1|1]; 76 Max[rt<<1|1] = -Min[rt<<1|1]; 77 Min[rt<<1|1] = tmp; 78 79 col[rt<<1] ^= 1; 80 col[rt<<1|1] ^= 1; 81 col[rt] ^= 1; 82 } 83 } 84 85 void build(int rt, int l, int r) 86 { 87 Min[rt] = INF; 88 Max[rt] = -INF; 89 col[rt] = 0; 90 if(l == r) return ; 91 int m = (l + r) >> 1; 92 build(lson); build(rson); 93 } 94 95 void update(int rt, int l, int r, int id, int w) // 更新边 96 { 97 if(l == r && l == id) { 98 Min[rt] = Max[rt] = w; 99 return ; 100 } 101 pushdown(rt); 102 int m = (l + r) >> 1; 103 if(id <= m) update(lson, id, w); 104 else update(rson, id, w); 105 pushup(rt); 106 } 107 108 void Update(int rt, int l, int r, int L, int R) // 翻转值 109 { 110 int tmp; 111 if(L <= l && r <= R) { 112 tmp = -Max[rt]; 113 Max[rt] = -Min[rt]; 114 Min[rt] = tmp; 115 col[rt] ^= 1; 116 return ; 117 } 118 pushdown(rt); 119 int m = (l + r) >> 1; 120 if(L <= m) Update(lson, L, R); 121 if(R > m) Update(rson, L, R); 122 pushup(rt); 123 } 124 125 int query(int rt, int l, int r, int L, int R) 126 { 127 int ans = -INF; 128 if(L <= l && r <= R) { 129 ans = max(ans, Max[rt]); 130 return ans; 131 } 132 pushdown(rt); 133 int m = (l + r) >> 1; 134 if(L <= m) ans = max(ans, query(lson, L, R)); 135 if(m < R) ans = max(ans, query(rson, L, R)); 136 return ans; 137 } 138 139 int change(int u, int v) // 查询 (u, v) 最长距离 140 { 141 int ans = -INF; 142 while(top[u] != top[v]) { 143 if(dep[top[u]] < dep[top[v]]) swap(u, v); 144 ans = max(ans, query(1, 1, time, tid[top[u]], tid[u])); 145 u = fa[top[u]]; 146 } 147 if(u == v) return ans; 148 if(dep[u] > dep[v]) swap(u, v); 149 ans = max(ans, query(1, 1, time, tid[son[u]], tid[v])); 150 return ans; 151 } 152 153 void uuu(int u, int v) // 将值翻转 154 { 155 while(top[u] != top[v]) { 156 if(dep[top[u]] < dep[top[v]]) swap(u, v); 157 Update(1, 1, time, tid[top[u]], tid[u]); 158 u = fa[top[u]]; 159 } 160 if(u == v) return ; 161 if(dep[u] > dep[v]) swap(u, v); 162 Update(1, 1, time, tid[son[u]], tid[v]); 163 } 164 165 int main() 166 { 167 int t; 168 scanf("%d", &t); 169 while(t--) { 170 int n; 171 scanf("%d", &n); 172 init(); 173 for(int i = 1; i < n; i++) { 174 scanf("%d%d%d", &e[i][0], &e[i][1], &e[i][2]); 175 add(e[i][0], e[i][1], e[i][2]); 176 add(e[i][1], e[i][0], e[i][2]); 177 } 178 dfs1(1, 1, 1); 179 dfs2(1, 1); 180 build(1, 1, time); 181 for(int i = 1; i < n; i++) { 182 if(dep[e[i][0]] > dep[e[i][1]]) swap(e[i][0], e[i][1]); 183 update(1, 1, time, tid[e[i][1]], e[i][2]); 184 } 185 char s[10]; 186 int a, b; 187 while(scanf("%s", s) == 1) { 188 if(s[0] == 'D') break; 189 scanf("%d%d", &a, &b); 190 if(s[0] == 'Q') { 191 printf("%d\n", change(a, b)); 192 } else if(s[0] == 'N') { 193 uuu(a, b); 194 } else { 195 update(1, 1, time, tid[e[a][1]], b); 196 } 197 } 198 } 199 return 0; 200 } 201 202 /* 203 1 204 205 3 206 1 2 1 207 2 3 2 208 QUERY 1 2 209 CHANGE 1 3 210 QUERY 1 2 211 NEGATE 1 3 212 QUERY 1 3 213 DONE 214 */