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.

 

你可能感兴趣的:(ZOJ)