POJ 3237 Tree (树链剖分 路径剖分 线段树的lazy标记)

题目链接: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
" , 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 }
原文地址:https://www.cnblogs.com/Recoder/p/5521216.html