[BZOJ1984]月下“毛景树”解题报告|树链剖分
Description
毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园。 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里。爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~~~ “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数: Change k w:将第k条树枝上毛毛果的个数改变为w个。 Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。 Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问: Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。树”下面,发现树上长着他最爱吃的毛毛果~~~ “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数: Change k w:将第k条树枝上毛毛果的个数改变为w个。 Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。 Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问: Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。
这道题可讲之处显然都在线段树上了...
事实证明现在的泪都是当年学线段树时脑子进的水...
1 program bzoj1984; 2 const maxn=100010;maxm=200010; 3 var n,i,j,x,y,z,cnt,t:longint; 4 ch:char; 5 ter,next,w:array[-1..maxm]of longint; 6 link,deep,size,v,son,pos,belong:array[-1..maxn]of longint; 7 tr:array[-1..5*maxn]of record l,r,mx,add,c:longint;wait:boolean;end; 8 fa:array[-1..maxn,-1..20]of longint; 9 10 function max(a,b:longint):longint; 11 begin 12 if a>b then exit(a) else exit(b); 13 end; 14 15 procedure add(x,y,z:longint); 16 begin 17 inc(j);ter[j]:=y;next[j]:=link[x];link[x]:=j;w[j]:=z; 18 inc(j);ter[j]:=x;next[j]:=link[y];link[y]:=j;w[j]:=z; 19 end; 20 21 procedure dfs1(p:longint); 22 var i,j:longint; 23 begin 24 size[p]:=1; 25 for i:=1 to 17 do 26 begin 27 if deep[p]<=1 << i then break; 28 fa[p][i]:=fa[fa[p][i-1]][i-1]; 29 end; 30 j:=link[p]; 31 while j<>0 do 32 begin 33 if deep[ter[j]]=0 then 34 begin 35 deep[ter[j]]:=deep[p]+1; 36 fa[ter[j]][0]:=p; 37 v[ter[j]]:=w[j];son[(j+1) >> 1]:=ter[j]; 38 dfs1(ter[j]); 39 inc(size[p],size[ter[j]]); 40 end; 41 j:=next[j]; 42 end; 43 end; 44 45 procedure dfs2(p,chain:longint); 46 var j,k:longint; 47 begin 48 inc(cnt);pos[p]:=cnt;belong[p]:=chain; 49 k:=0; 50 j:=link[p]; 51 while j<>0 do 52 begin 53 if deep[ter[j]]>deep[p] then 54 if size[ter[j]]>size[k] then k:=ter[j]; 55 j:=next[j]; 56 end; 57 if k=0 then exit; 58 dfs2(k,chain); 59 j:=link[p]; 60 while j<>0 do 61 begin 62 if deep[ter[j]]>deep[p] then 63 if k<>ter[j] then dfs2(ter[j],ter[j]); 64 j:=next[j]; 65 end; 66 end; 67 68 procedure build(p,l,r:longint); 69 var mid:longint; 70 begin 71 tr[p].l:=l;tr[p].r:=r;tr[p].mx:=0;tr[p].wait:=false;tr[p].add:=0; 72 if l=r then exit; 73 mid:=(l+r) >> 1; 74 build(p << 1,l,mid); 75 build(p << 1+1,mid+1,r); 76 end; 77 78 procedure push(p:longint); 79 begin 80 if tr[p].l=tr[p].r then exit; 81 if tr[p].wait then 82 begin 83 //与上一题不同,这一题并不存在下面的点在更新之后能比现在更好的情况所以不需要push(p << 1);push(p << 1+1) 84 //否则会TLE 85 tr[p << 1].add:=0;tr[p << 1+1].add:=0; 86 //这两句很关键 因为当儿子节点再往下更新的时候如果add没有清零再往下的点会被赋上不等于tr[p].mx的值 87 tr[p << 1].mx:=tr[p].mx;tr[p << 1].wait:=true; 88 tr[p << 1+1].mx:=tr[p].mx;tr[p << 1+1].wait:=true; 89 tr[p].wait:=false; 90 tr[p].mx:=max(tr[p << 1].mx,tr[p << 1+1].mx); 91 end; 92 if tr[p].add<>0 then 93 begin 94 inc(tr[p << 1].mx,tr[p].add); 95 if not tr[p << 1].wait then inc(tr[p << 1].add,tr[p].add); 96 //这个特判很关键也很隐蔽 因为如果tr[p << 1].wait=True的话它往下传的时候应该把tr[p << 1].mx+tr[p].add传递下去 97 //但是如果把tr[p << 1].add也加上了tr[p].add的话相当于重复相加 就出错了 98 inc(tr[p << 1+1].mx,tr[p].add); 99 if not tr[p << 1+1].wait then inc(tr[p << 1+1].add,tr[p].add); 100 tr[p].add:=0; 101 tr[p].mx:=max(tr[p << 1].mx,tr[p << 1+1].mx); 102 end; 103 end; 104 105 procedure insert(p,l,r,ave:longint); 106 var mid:longint; 107 begin 108 push(p); 109 if (tr[p].l=l)and(tr[p].r=r) then 110 begin 111 tr[p].mx:=ave;tr[p].wait:=true; 112 exit; 113 end; 114 mid:=(tr[p].l+tr[p].r) >> 1; 115 if r<=mid then insert(p << 1,l,r,ave) else 116 if l>mid then insert(p << 1+1,l,r,ave) else 117 begin 118 insert(p << 1,l,mid,ave); 119 insert(p << 1+1,mid+1,r,ave); 120 end; 121 tr[p].mx:=max(tr[p << 1].mx,tr[p << 1+1].mx); 122 end; 123 124 function lca(x,y:longint):longint; 125 var tem,i:longint; 126 begin 127 if deep[x]<deep[y] then 128 begin 129 tem:=x;x:=y;y:=tem; 130 end; 131 if deep[x]<>deep[y] then 132 begin 133 i:=trunc(ln(deep[x]-deep[y])/ln(2)); 134 while deep[x]>deep[y] do 135 begin 136 while (deep[x]-deep[y]>=1 << i) do x:=fa[x][i]; 137 dec(i); 138 end; 139 end; 140 if x=y then exit(x); 141 i:=trunc(ln(n)/ln(2)); 142 while fa[x][0]<>fa[y,0] do 143 begin 144 while fa[x,i]<>fa[y,i] do 145 begin 146 x:=fa[x,i];y:=fa[y,i]; 147 end; 148 dec(i); 149 end; 150 exit(fa[x,0]); 151 end; 152 153 procedure add(p,l,r,ave:longint); 154 var mid:longint; 155 begin 156 push(p); 157 if (tr[p].l=l)and(tr[p].r=r) then 158 begin 159 inc(tr[p].mx,ave); 160 inc(tr[p].add,ave); 161 exit; 162 end; 163 mid:=(tr[p].l+tr[p].r) >> 1; 164 if r<=mid then add(p << 1,l,r,ave) else 165 if l>mid then add(p << 1+1,l,r,ave) else 166 begin 167 add(p << 1,l,mid,ave); 168 add(p << 1+1,mid+1,r,ave); 169 end; 170 tr[p].mx:=max(tr[p << 1].mx,tr[p << 1+1].mx); 171 end; 172 173 function query(p,l,r:longint):longint; 174 var mid:longint; 175 begin 176 push(p); 177 if (tr[p].l=l)and(tr[p].r=r) then exit(tr[p].mx); 178 mid:=(tr[p].l+tr[p].r) >> 1; 179 if r<=mid then exit(query(p << 1,l,r)) else 180 if l>mid then exit(query(p << 1+1,l,r)) else 181 exit(max(query(p << 1,l,mid),query(p << 1+1,mid+1,r))); 182 end; 183 184 procedure solve_change(x,y,z:longint); 185 begin 186 while belong[x]<>belong[y] do 187 begin 188 insert(1,pos[belong[x]],pos[x],z); 189 x:=fa[belong[x]][0]; 190 end; 191 if x<>y then insert(1,pos[y]+1,pos[x],z); 192 end; 193 194 procedure solve_add(x,y,z:longint); 195 begin 196 while belong[x]<>belong[y] do 197 begin 198 add(1,pos[belong[x]],pos[x],z); 199 x:=fa[belong[x]][0]; 200 end; 201 if x<>y then add(1,pos[y]+1,pos[x],z); 202 end; 203 204 function solve_mx(x,y:longint):longint; 205 var sum:longint; 206 begin 207 sum:=0; 208 while belong[x]<>belong[y] do 209 begin 210 sum:=max(sum,query(1,pos[belong[x]],pos[x])); 211 x:=fa[belong[x]][0]; 212 end; 213 if x<>y then sum:=max(sum,query(1,pos[y]+1,pos[x])); 214 exit(sum); 215 end; 216 217 begin 218 readln(n); 219 j:=0; 220 for i:=1 to n-1 do 221 begin 222 readln(x,y,z); 223 add(x,y,z); 224 end; 225 deep[1]:=1;dfs1(1); 226 cnt:=0;dfs2(1,1); 227 build(1,1,n); 228 for i:=1 to n do insert(1,pos[i],pos[i],v[i]); 229 read(ch); 230 while ch<>'S' do 231 begin 232 if ch='C' then 233 begin 234 read(ch); 235 if ch='h' then 236 begin 237 readln(ch,ch,ch,ch,x,y); 238 insert(1,pos[son[x]],pos[son[x]],y); 239 end else 240 begin 241 readln(ch,ch,ch,x,y,z); 242 t:=lca(x,y); 243 solve_change(x,t,z);solve_change(y,t,z); 244 end; 245 end else 246 if ch='A' then 247 begin 248 readln(ch,ch,x,y,z); 249 t:=lca(x,y); 250 solve_add(x,t,z);solve_add(y,t,z); 251 end else 252 begin 253 readln(ch,ch,x,y); 254 t:=lca(x,y); 255 writeln(max(solve_mx(x,t),solve_mx(y,t))); 256 end; 257 read(ch); 258 end; 259 end. 260