标签:
题目链接:http://poj.org/problem?id=3237
一棵有边权的树,有3种操作。
树链剖分+线段树lazy标记。lazy为0表示没更新区间或者区间更新了2的倍数次,1表示为更新,每次更新异或1就可以。
熟悉线段树成段更新就很简单了,最初姿势不对一直wa,还是没有彻底理解lazy标记啊。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 const int MAXN = 1e4 + 5; 6 struct EDGE { 7 int next , to , cost; 8 }edge[MAXN << 1]; 9 int head[MAXN] , tot; 10 int par[MAXN] , size[MAXN] , son[MAXN] , dep[MAXN]; 11 int top[MAXN] , id[MAXN] , cnt; 12 int from[MAXN] , to[MAXN] , cost[MAXN]; 13 14 void init() { 15 tot = cnt = 0; 16 memset(head , -1 , sizeof(head)); 17 } 18 19 inline void add(int u , int v , int cost) { 20 edge[tot].next = head[u]; 21 edge[tot].to = v; 22 head[u] = tot++; 23 } 24 25 void dfs1(int u , int p , int d) { 26 par[u] = p , size[u] = 1 , son[u] = u , dep[u] = d; 27 for(int i = head[u] ; ~i ; i = edge[i].next) { 28 int v = edge[i].to; 29 if(v == p) 30 continue; 31 dfs1(v , u , d + 1); 32 if(size[v] >= size[son[u]]) 33 son[u] = v; 34 size[u] += size[v]; 35 } 36 } 37 38 void dfs2(int u , int p , int t) { 39 top[u] = t , id[u] = ++cnt; 40 if(son[u] != u) 41 dfs2(son[u] , u , t); 42 for(int i = head[u] ; ~i ; i = edge[i].next) { 43 int v = edge[i].to; 44 if(v == p || v == son[u]) 45 continue; 46 dfs2(v , u , v); 47 } 48 } 49 50 struct SegTree { 51 int l , r , Max , lazy , Min; //lazy变量0表示无更新 1表示有更新 52 }T[MAXN << 2]; 53 54 void build(int p , int l , int r) { 55 int mid = (l + r) >> 1; 56 T[p].l = l , T[p].r = r , T[p].lazy = 0; 57 if(l == r) { 58 return ; 59 } 60 build(p << 1 , l , mid); 61 build((p << 1)|1 , mid + 1 , r); 62 } 63 64 void pushup(int p) { 65 if(T[p].lazy) { 66 int ls = p << 1 , rs = (p << 1)|1; 67 T[ls].lazy ^= 1; 68 T[rs].lazy ^= 1; 69 70 int temp; 71 temp = T[ls].Max; 72 T[ls].Max = -T[ls].Min; 73 T[ls].Min = -temp; 74 75 temp = T[rs].Max; 76 T[rs].Max = -T[rs].Min; 77 T[rs].Min = -temp; 78 T[p].lazy = 0; 79 } 80 } 81 //更新操作就是 将原来的Max变成-Min ,Min变成-Max 82 void updata(int p , int l , int r , int flag) { 83 int mid = (T[p].r + T[p].l) >> 1; 84 if(T[p].l == l && T[p].r == r) { 85 T[p].lazy ^= flag; 86 int temp = T[p].Max; 87 T[p].Max = -T[p].Min; 88 T[p].Min = -temp; 89 return ; 90 } 91 pushup(p); 92 if(r <= mid) { 93 updata(p << 1 , l , r , flag); 94 } 95 else if(l > mid) { 96 updata((p << 1)|1 , l , r , flag); 97 } 98 else { 99 updata(p << 1 , l , mid , flag); 100 updata((p << 1)|1 , mid + 1 , r , flag); 101 } 102 T[p].Max = max(T[p << 1].Max , T[(p << 1)|1].Max); 103 T[p].Min = min(T[p << 1].Min , T[(p << 1)|1].Min); 104 } 105 106 int query(int p , int l , int r) { 107 int mid = (T[p].l + T[p].r) >> 1; 108 if(T[p].l == l && T[p].r == r) { 109 return T[p].Max; 110 } 111 pushup(p); 112 if(r <= mid) { 113 return query(p << 1 , l , r); 114 } 115 else if(l > mid) { 116 return query((p << 1)|1 , l , r); 117 } 118 else { 119 return max(query(p << 1 , l , mid) , query((p << 1)|1 , mid + 1 , r)); 120 } 121 } 122 123 void updata_pos(int p , int pos , int num) { 124 int mid = (T[p].l + T[p].r) >> 1; 125 if(T[p].l == T[p].r && T[p].l == pos) { 126 T[p].Max = T[p].Min = num; 127 T[p].lazy = 0; 128 return ; 129 } 130 pushup(p); 131 if(pos <= mid) { 132 updata_pos(p << 1 , pos , num); 133 } 134 else { 135 updata_pos((p << 1)|1 , pos , num); 136 } 137 T[p].Max = max(T[p << 1].Max , T[(p << 1)|1].Max); 138 T[p].Min = min(T[p << 1].Min , T[(p << 1)|1].Min); 139 } 140 141 int find_max(int u , int v) { 142 int fu = top[u] , fv = top[v] , Max = -99999999; 143 while(fv != fu) { 144 if(dep[fu] > dep[fv]) { 145 Max = max(Max , query(1 , id[fu] , id[u])); 146 u = par[fu]; 147 fu = top[u]; 148 } 149 else { 150 Max = max(Max , query(1 , id[fv] , id[v])); 151 v = par[fv]; 152 fv = top[v]; 153 } 154 } 155 if(v == u) 156 return Max; 157 else if(dep[u] > dep[v]) 158 return max(Max , query(1 , id[son[v]] , id[u])); 159 else 160 return max(Max , query(1 , id[son[u]] , id[v])); 161 } 162 163 void change(int u , int v) { 164 int fu = top[u] , fv = top[v]; 165 while(fu != fv) { 166 if(dep[fu] > dep[fv]) { 167 updata(1 , id[fu] , id[u] , 1); 168 u = par[fu]; 169 fu = top[u]; 170 } 171 else { 172 updata(1 , id[fv] , id[v] , 1); 173 v = par[fv]; 174 fv = top[v]; 175 } 176 } 177 if(v == u) 178 return ; 179 else if(dep[u] > dep[v]) 180 updata(1 , id[son[v]] , id[u] , 1); 181 else 182 updata(1 , id[son[u]] , id[v] , 1); 183 } 184 185 int main() 186 { 187 int t, n; 188 scanf("%d", &t); 189 while(t--) { 190 init(); 191 scanf("%d" , &n); 192 for(int i = 1 ; i < n ; ++i) { 193 scanf("%d %d %d" , from + i , to + i , cost + i); 194 add(from[i] , to[i] , cost[i]); 195 add(to[i] , from[i] , cost[i]); 196 } 197 dfs1(1 , 1 , 0); 198 dfs2(1 , 1 , 1); 199 build(1 , 2 , cnt); 200 for(int i = 1 ; i < n ; ++i) { 201 if(dep[from[i]] < dep[to[i]]) 202 swap(from[i] , to[i]); 203 updata_pos(1 , id[from[i]] , cost[i]); 204 } 205 char q[10]; 206 int l , r; 207 while(scanf("%s" , q) && q[0] != ‘D‘) { 208 scanf("%d %d" , &l , &r); 209 if(q[0] == ‘Q‘) { 210 printf("%d\n" , find_max(l , r)); 211 } 212 else if(q[0] == ‘N‘) { 213 change(l , r); 214 } 215 else { 216 updata_pos(1 , id[from[l]] , r); 217 } 218 } 219 } 220 return 0; 221 }
POJ 3237 Tree (树链剖分 路径剖分 线段树的lazy标记)
标签:
原文地址:http://www.cnblogs.com/Recoder/p/5521216.html