[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     

 

 
posted @ 2015-04-11 14:50  mjy0724  阅读(190)  评论(0编辑  收藏  举报