1984: 月下“毛景树”
2015-05-13 21:46
204 查看
1984: 月下“毛景树”
Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 1003 Solved: 324
[Submit][Status][Discuss]
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之间树枝上毛毛果个数最多有多少个。Input
第一行一个正整数N。 接下来N-1行,每行三个正整数Ui,Vi和Wi,第i+1行描述第i条树枝。表示第i条树枝连接节点Ui和节点Vi,树枝上有Wi个毛毛果。 接下来是操作和询问,以“Stop”结束。Output
对于毛毛虫的每个询问操作,输出一个答案。Sample Input
41 2 8
1 3 7
3 4 9
Max 2 4
Cover 2 4 5
Add 1 4 10
Change 1 16
Max 2 4
Stop
Sample Output
916
【Data Range】
1<=N<=100,000,操作+询问数目不超过100,000。
保证在任意时刻,所有树枝上毛毛果的个数都不会超过10^9个。
HINT
Source
树的分治题解:不用多说,又是一个树链剖分。。。只不过这里面要维护的是树上各个边的权值,不再是点的权值了,于是本蒟蒻由于懒得想边维护怎么搞所以直接想了个神(dou)奇(bi)办法将边维护转化为了点维护问题——
对于一个边而言,显然连接着两个点,然后当我们建立完有根树之后,每个边则会对应着唯一的一个下方的节点(而且显然除了根节点之外每个点都刚刚好对应一条边),然后边的维护就成功转化为了点的维护问题了,唯一的不同在于当你每次进行树上操作的时候记得一定要排除两个点LCA位置的那个点(HansBug:因为那个点对应着该条链之外的一条边,而别的点对应的则均为该链上的^_^)
然后接下来就是漫漫的Debug之路了,然后弄来弄去发现还是爆栈了TT,其实只要一个编译开关就可以啦,详见程序第一行
/************************************************************** Problem: 1984 User: HansBug Language: Pascal Result: Accepted Time:13800 ms Memory:58596 kb ****************************************************************/ {$M 6552000,0,655360000} type point=^node; node=record g,f:longint; next:point;w:int64; end; var i,j,k,l,m,n,tot,root:longint;ch:char; a:array[0..100005] of point; e:array[0..1000005,0..3] of int64; c:array[0..20,0..100005] of longint; d:array[0..1000005] of int64; f:array[0..100005] of int64; top,tip,len,siz,son,g,num,anum:array[0..100005] of longint; procedure swap(var x,y:longint); var z:longint; begin z:=x;x:=y;y:=z; end; function max(x,y:longint):longint; begin if x>y then max:=x else max:=y; end; function min(x,y:longint):longint; begin if x<y then min:=x else min:=y; end; procedure add(x,y,z,t:longint); var p:point; begin new(p);p^.g:=y;p^.w:=z;p^.f:=t; p^.next:=a[x];a[x]:=p; end; procedure dfs(y,x:longint); var p:point; begin len[x]:=len[y]+1; c[0,x]:=y;siz[x]:=1; son[x]:=0;p:=a[x]; while p<>nil do begin if p^.g<>y then begin dfs(x,p^.g);tip[p^.w]:=p^.g;f[p^.g]:=p^.f; if (son[x]=0) or (siz[p^.g]>siz[son[x]]) then son[x]:=p^.g; inc(siz[x],siz[p^.g]); end; p:=p^.next; end; end; procedure dfs2(y,x,z:longint); var p:point; begin top[x]:=z;inc(tot);num[x]:=tot;anum[tot]:=x; if son[x]<>0 then dfs2(x,son[x],z);p:=a[x]; while p<>nil do begin if (p^.g<>y) and (p^.g<>son[x]) then dfs2(x,p^.g,p^.g); p:=p^.next; end; end; procedure ext(z,x,y:longint); begin if e[z,1]<>0 then begin d[z]:=e[z,2]; if x<>y then begin e[z*2,1]:=1;e[z*2,2]:=e[z,2]; e[z*2+1,1]:=1;e[z*2+1,2]:=e[z,2]; end; e[z,2]:=0;e[z,1]:=0;e[z,3]:=0; end else if e[z,3]<>0 then begin inc(d[z],e[z,3]); if x<>y then begin if e[z*2,1]<>0 then ext(z*2,x,(x+y) div 2); if e[z*2+1,1]<>0 then ext(z*2+1,(x+y) div 2+1,y); inc(e[z*2,3],e[z,3]); inc(e[z*2+1,3],e[z,3]); end; e[z,3]:=0;e[z,2]:=0;e[z,1]:=0; end; end; procedure built(z,x,y:longint); begin if x=y then d[z]:=f[anum[x]] else begin built(z*2,x,(x+y) div 2); built(z*2+1,(x+y) div 2+1,y); if d[z*2]>d[z*2+1] then d[z]:=d[z*2] else d[z]:=d[z*2+1]; end; e[z,1]:=0;e[z,2]:=0;e[z,3]:=0; end; function addd(z,x,y,l,r:longint;t:int64):int64; var a1,a2:int64; begin if l>r then begin ext(z,x,y); exit(d[z]); end; ext(z,x,y);if (x=l) and (y=r) then begin inc(e[z,3],t); exit(d[z]+e[z,3]); end; a1:=addd(z*2,x,(x+y) div 2,l,min(r,(x+y) div 2),t); a2:=addd(z*2+1,(x+y) div 2+1,y,max((x+y) div 2+1,l),r,t); if a1>a2 then d[z]:=a1 else d[z]:=a2; exit(d[z]); end; function cover(z,x,y,l,r:longint;t:int64):int64; var a1,a2:int64; begin if l>r then begin ext(z,x,y); exit(d[z]); end; if (x=l) and (y=r) then begin e[z,1]:=1; e[z,2]:=t; exit(t); end; ext(z,x,y); a1:=cover(z*2,x,(x+y) div 2,l,min(r,(x+y) div 2),t); a2:=cover(z*2+1,(x+y) div 2+1,y,max((x+y) div 2+1,l),r,t); if a1>a2 then d[z]:=a1 else d[z]:=a2; exit(d[z]); end; function getmax(z,x,y,l,r:longint):int64; begin if l>r then exit(-maxlongint); if e[z,1]<>0 then exit(e[z,2]); ext(z,x,y); if (x=l) and (y=r) then exit(d[z]); exit(max(getmax(z*2,x,(x+y) div 2,l,min(r,(x+y) div 2)),getmax(z*2+1,(x+y) div 2+1,y,max((x+y) div 2+1,l),r))); end; function getup(x,y:longint):longint; var i:longint; begin i:=0; while y<>0 do begin if odd(y) then x:=c[i,x]; inc(i);y:=y div 2; end; exit(x); end; function getcom(x,y:longint):longint; var i:longint; begin if len[x]<len[y] then swap(x,y); x:=getup(x,len[x]-len[y]); if x=y then exit(x); for i:=trunc(round(ln(len[x])/ln(2))) downto 0 do if c[i,x]<>c[i,y] then begin x:=c[i,x]; y:=c[i,y]; end; exit(c[0,x]); end; procedure treechange(x,y:longint;t:int64); var i,z,z1:longint; begin z:=getcom(x,y); if x<>z then begin z1:=getup(x,len[x]-len[z]-1); repeat if len[top[x]]<len[z1] then i:=z1 else i:=top[x]; cover(1,1,n,num[i],num[x],t); if i=z1 then break; x:=c[0,i]; until false; end; if y<>z then begin z1:=getup(y,len[y]-len[z]-1); repeat if len[top[y]]<len[z1] then i:=z1 else i:=top[y]; cover(1,1,n,num[i],num[y],t); if i=z1 then break; y:=c[0,i]; until false; end; end; procedure treeadd(x,y:longint;t:int64); var z,i,z1:longint; begin z:=getcom(x,y); if x<>z then begin z1:=getup(x,len[x]-len[z]-1); repeat if len[top[x]]<len[z1] then i:=z1 else i:=top[x]; addd(1,1,n,num[i],num[x],t); if i=z1 then break; x:=c[0,i]; until false; end; if y<>z then begin z1:=getup(y,len[y]-len[z]-1); repeat if len[top[y]]<len[z1] then i:=z1 else i:=top[y]; addd(1,1,n,num[i],num[y],t); if i=z1 then break; y:=c[0,i]; until false; end; end; function treemax(x,y:longint):int64; var i,z,z1:longint;a1:int64; begin z:=getcom(x,y);treemax:=0; if x<>z then begin z1:=getup(x,len[x]-len[z]-1); repeat if len[top[x]]<len[z1] then i:=z1 else i:=top[x]; a1:=getmax(1,1,n,num[i],num[x]); if a1>treemax then treemax:=a1; if i=z1 then break; x:=c[0,i]; until false; end; if y<>z then begin z1:=getup(y,len[y]-len[z]-1); repeat if len[top[y]]<len[z1] then i:=z1 else i:=top[y]; a1:=getmax(1,1,n,num[i],num[y]); if a1>treemax then treemax:=a1; if i=z1 then break; y:=c[0,i]; until false; end; end; begin readln(n); for i:=1 to n do a[i]:=nil; for i:=1 to n-1 do begin readln(j,k,l); add(j,k,i,l);add(k,j,i,l); end; root:=random(n)+1;dfs(0,root);dfs2(0,root,root); for i:=1 to trunc(round(ln(n)/ln(2))) do for j:=1 to n do c[i,j]:=c[i-1,c[i-1,j]]; built(1,1,n); while not(eof) do begin read(ch,ch); case upcase(ch) of 'A':begin readln(ch,i,j); writeln(treemax(i,j)); end; 'O':begin readln(ch,ch,ch,i,j,k); treechange(i,j,k); end; 'D':begin readln(ch,i,j,k); treeadd(i,j,k); end; 'H':begin readln(ch,ch,ch,ch,i,j); treechange(c[0,tip[i]],tip[i],j); end; 'T':halt; end; end; end.
相关文章推荐
- [bzoj1984]月下“毛景树” 树链剖分
- 【BZOJ-1984】月下“毛景树” 树链剖分
- bzoj 1984: 月下“毛景树”
- [BZOJ1984]月下“毛景树”(树链剖分)
- BZOJ 1984 月下“毛景树”
- 【BZOJ】1984 月下“毛景树”
- [BZOJ]1984: 月下“毛景树”
- BZOJ1984: 月下“毛景树”
- BZOJ 1984: 月下“毛景树”( 树链剖分 )
- [BZOJ1984]月下“毛景树”(树链剖分)
- 【bzoj1984】【坑】月下“毛景树” 树链剖分
- 【BZOJ1984】月下“毛景树”-树链剖分
- bzoj 1984: 月下“毛景树” 线段树+树链剖分
- BZOJ1984: 月下“毛景树”
- bzoj 1984: 月下“毛景树” (树链剖分)
- bzoj1984 月下“毛景树”树链剖分 线段树
- 【BZOJ1984】月下“毛景树” 树链剖分+线段树
- 【BZOJ】【P1984】【月下“毛景树”】【题解】【链剖线段树】
- 【树链剖分】【分块】【最近公共祖先】【块状树】bzoj1984 月下“毛景树”
- bzoj1984 月下“毛景树”