您的位置:首页 > 其它

1984: 月下“毛景树”

2015-05-13 21:46 204 查看

1984: 月下“毛景树”

Time Limit: 20 Sec Memory Limit: 64 MB
Submit: 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

4

1 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

9

16

【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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: