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.