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 *************
");
142     printf("%d
", 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
", 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
", 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
", 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 */
原文地址:https://www.cnblogs.com/fightfordream/p/6016665.html