bzoj 2243 树链剖分

2013-11-19 16:21

原题传送门http://www.lydsy.com/JudgeOnline/problem.php?id=2243

树链剖分,用线段树记录该区间的颜色段数,左右端点颜色数,然后就OK了

  1 //By BLADEVIL
  2 type
  3     rec                                 =record
  4         sum, left, right, succ, pred    :longint;
  5         lazy                            :longint;
  6     end;
  7      
  8 var
  9     n                                   :longint;
 10     pre, other                          :array[0..2000100] of longint;
 11     last                                :array[0..1000100] of longint;
 12     m                                   :longint;
 13     color                               :array[0..1000100] of longint;
 14     father, size, max_son               :array[0..1000100] of longint;
 15     dep, top, a, num                    :array[0..1000100] of longint;
 16     tot                                 :longint;
 17     flag                                :array[0..1000100] of boolean;
 18     l                                   :longint;
 19     t                                   :array[0..4000100] of rec;
 20      
 21 procedure swap(var a,b:longint);
 22 var
 23     c                                   :longint;
 24 begin
 25     c:=a; a:=b; b:=c;
 26 end;
 27      
 28 procedure connect(x,y:longint);
 29 begin
 30     inc(l);
 31     pre[l]:=last[x];
 32     last[x]:=l;
 33     other[l]:=y;
 34 end;
 35  
 36 procedure dfs(x:longint);
 37 var
 38     q, p                                :longint;
 39 begin
 40     size[x]:=1;
 41     q:=last[x];
 42     while q<>0 do
 43     begin
 44         p:=other[q];
 45         if not flag[p] then
 46         begin
 47             father[p]:=x;
 48             flag[p]:=true;
 49             dfs(p);
 50             inc(size[x],size[p]);
 51             if size[max_son[x]]<size[p] then max_son[x]:=p;
 52         end;
 53         q:=pre[q];
 54     end;
 55 end;
 56  
 57 procedure make(x,t,depth:longint);
 58 var
 59     q, p                                :longint;
 60 begin
 61     inc(tot);
 62     num[x]:=tot;
 63     top[x]:=t;
 64     a[tot]:=color[x];
 65     dep[x]:=depth;
 66     if (max_son[x]<>0) and (not flag[max_son[x]]) then
 67     begin
 68         flag[max_son[x]]:=true;
 69         make(max_son[x],t,depth);
 70     end;
 71     q:=last[x];
 72     while q<>0 do
 73     begin
 74         p:=other[q];
 75         if not flag[p] then
 76         begin
 77             flag[p]:=true;
 78             make(p,p,depth+1);
 79         end;
 80         q:=pre[q];
 81     end;
 82 end;
 83      
 84 procedure build(x,l,r:longint);
 85 var
 86     mid                                 :longint;
 87 begin
 88     t[x].left:=l; t[x].right:=r;
 89     if l=r then
 90     begin
 91         t[x].sum:=1;
 92         t[x].succ:=a[l];
 93         t[x].pred:=a[l];
 94         exit;
 95     end;
 96     mid:=(l+r) div 2;
 97     build(x*2,l,mid);
 98     build(x*2+1,mid+1,r);
 99     t[x].succ:=t[x*2].succ;
100     t[x].pred:=t[x*2+1].pred;
101     if t[x*2].pred=t[x*2+1].succ then
102         t[x].sum:=t[x*2].sum+t[x*2+1].sum-1 else
103         t[x].sum:=t[x*2].sum+t[x*2+1].sum;
104 end;    
105      
106 procedure init;
107 var
108     i                                   :longint;
109     x, y                                :longint;
110      
111 begin
112     read(n,m);
113     for i:=1 to n do read(color[i]);
114     for i:=1 to n-1 do
115     begin
116         read(x,y);
117         connect(x,y);
118         connect(y,x);
119     end;
120     flag[1]:=true;
121     dfs(1);
122     fillchar(flag,sizeof(flag),false);
123     flag[1]:=true;
124     make(1,1,1);
125     build(1,1,n);
126 end;
127  
128 procedure change(x,l,r,z:longint);
129 var
130     mid                                 :longint;
131 begin
132     if t[x].lazy<>0 then
133     begin
134 t[x*2].lazy:=t[x].lazy;
135         t[x*2].sum:=1;
136         t[x*2].succ:=t[x].lazy;
137         t[x*2].pred:=t[x].lazy;
138         t[x*2+1].lazy:=t[x].lazy;
139         t[x*2+1].sum:=1;
140         t[x*2+1].succ:=t[x].lazy;
141         t[x*2+1].pred:=t[x].lazy;
142         t[x].lazy:=0;
143     end;
144     if (t[x].left=l) and (t[x].right=r) then
145     begin
146         t[x].lazy:=z;
147         t[x].sum:=1;
148         t[x].succ:=z;
149         t[x].pred:=z;
150         exit;
151     end;
152     with t[x] do mid:=(left+right) div 2;
153     if mid<l then change(x*2+1,l,r,z) else
154     if mid>=r then change(x*2,l,r,z) else
155     begin
156         change(x*2,l,mid,z);
157         change(x*2+1,mid+1,r,z);
158     end;
159     t[x].succ:=t[x*2].succ;
160     t[x].pred:=t[x*2+1].pred;
161     if t[x*2].pred=t[x*2+1].succ then
162         t[x].sum:=t[x*2].sum+t[x*2+1].sum-1 else
163         t[x].sum:=t[x*2].sum+t[x*2+1].sum;
164 end;
165  
166 function ask(x,l,r:longint):rec;
167 var
168     mid                                 :longint;
169 t1, t2     :rec;
170 begin
171     if t[x].lazy<>0 then
172     begin
173         t[x*2].lazy:=t[x].lazy;
174         t[x*2].sum:=1;
175         t[x*2].succ:=t[x].lazy;
176         t[x*2].pred:=t[x].lazy;
177         t[x*2+1].lazy:=t[x].lazy;
178         t[x*2+1].sum:=1;
179         t[x*2+1].succ:=t[x].lazy;
180         t[x*2+1].pred:=t[x].lazy;
181         t[x].lazy:=0;
182     end;
183      
184     if (t[x].left=l) and (t[x].right=r) then
185     begin
186         ask.succ:=t[x].succ;
187         ask.pred:=t[x].pred;
188         ask.sum:=t[x].sum;
189         exit;
190     end;
191      
192     with t[x] do mid:=(left+right) div 2;
193     if mid<l then
194     begin
195 t2:=ask(x*2+1,l,r);
196         ask.succ:=t2.succ;
197         ask.pred:=t2.pred;
198         ask.sum:=t2.sum
199     end else
200     if mid>=r then
201     begin
202 t1:=ask(x*2,l,r);
203         ask.succ:=t1.succ;
204         ask.pred:=t1.pred;
205         ask.sum:=t1.sum
206     end else
207     begin
208 t1:=ask(x*2,l,mid); 
209 t2:=ask(x*2+1,mid+1,r);
210         ask.succ:=t1.succ;
211         ask.pred:=t2.pred;
212         if t1.pred=t2.succ then
213             ask.sum:=t1.sum+t2.sum-1 else
214             ask.sum:=t1.sum+t2.sum;
215     end;
216 end;
217  
218 procedure paint(x,y,z:longint);
219 begin
220     if dep[x]>dep[y] then swap(x,y);
221     while dep[x]<dep[y] do
222     begin
223         change(1,num[top[y]],num[y],z);
224         y:=father[top[y]];
225     end;
226     while top[x]<>top[y] do
227     begin
228         change(1,num[top[x]],num[x],z);
229         change(1,num[top[y]],num[y],z);
230         x:=father[top[x]];
231         y:=father[top[y]];
232     end;
233     x:=num[x];
234     y:=num[y];
235     if x>y then swap(x,y);
236     change(1,x,y,z);
237 end;
238  
239 procedure query(x,y:longint);
240 var
241     ans                                 :longint;
242     a, b                                :longint;
243 begin
244     ans:=0;
245     if dep[x]>dep[y] then swap(x,y);
246     while dep[x]<dep[y] do
247     begin
248         ans:=ans+ask(1,num[top[y]],num[y]).sum;
249         a:=ask(1,num[top[y]],num[top[y]]).succ;
250         b:=ask(1,num[father[top[y]]],num[father[top[y]]]).pred;
251         if a=b then dec(ans);
252         y:=father[top[y]];
253     end;
254     while top[x]<>top[y] do
255     begin
256         ans:=ans+ask(1,num[top[y]],num[y]).sum;
257         a:=ask(1,num[top[y]],num[top[y]]).succ;
258         b:=ask(1,num[father[top[y]]],num[father[top[y]]]).pred;
259         if a=b then dec(ans);
260         ans:=ans+ask(1,num[top[x]],num[x]).sum;
261         a:=ask(1,num[top[x]],num[top[x]]).succ;
262         b:=ask(1,num[father[top[x]]],num[father[top[x]]]).pred;
263         if a=b then dec(ans);
264         x:=father[top[x]];
265         y:=father[top[y]];
266     end;
267     x:=num[x];
268     y:=num[y];
269     if x>y then swap(x,y);
270     ans:=ans+ask(1,x,y).sum;
271     writeln(ans);
272 end;
273  
274 procedure main;
275 var
276     i                                   :longint;
277     c                                   :char;
278     x, y, z                             :longint;
279      
280 begin
281     readln;
282     for i:=1 to m do
283     begin
284         read(c);
285         if c='Q' then
286         begin
287             readln(x,y);
288             query(x,y) 
289         end else
290         begin
291             readln(x,y,z);
292             paint(x,y,z);
293         end;
294     end;
295 end;
296  
297 begin
298     init;
299     main;
300 end.
原文地址:https://www.cnblogs.com/BLADEVIL/p/3433551.html