块状树(count)

本文介绍了如何利用块状树数据结构解决ZJOI2008比赛中的计数问题。文章详细阐述了块状树的概念,并通过实例展示了其在求解特定问题时的应用。
摘要由CSDN通过智能技术生成

原题:ZJOI2008 count

方法:块状树

program count_trees;{$M 9999999}
const maxn=30000+20;
type
    link=^node; node=record x:longint; next:link; end;
var
    own,w,dep,sum,size,fa,mun:array[0..maxn]of longint;
    ge,g:array[1..maxn]of link; limit:longint;
 
procedure update(var x:longint; const y:longint);
begin
    if y>x then x:=y;
end;
procedure push(var x:link; const t:longint);var p:link;
begin
    new(p);p^.x:=t;p^.next:=x;x:=p;
end;
 
procedure build(const x,f,d:longint);
var p:link;tmp:longint;
begin
    fa[x]:=f; dep[x]:=d; tmp:=own[x];
    p:=ge[x];while p<>nil do begin
        if p^.x<>f then begin
        if size[tmp]<limit then begin
            inc(size[tmp]);own[p^.x]:=tmp;
            push(g[x],p^.x);
        end;build(p^.x,x,d+1);end;
        p:=p^.next;
    end;
end;
 
procedure dfs(x,s,m:longint);var p:link;
begin
    inc(s,w[x]);sum[x]:=s;
    update(m,w[x]);mun[x]:=m;
    p:=g[x];while p<>nil do begin Dfs(p^.x,s,m);p:=p^.next;end;
end;
 
procedure change(x,y:longint);
begin
    w[x]:=y;if x=own[x] then Dfs(x,0,-maxlongint)
    else dfs(x,sum[fa[x]],mun[fa[x]]);
end;
 
procedure get_answer(a,b:longint; var s,m:longint);
procedure swap(var i,j:longint);var t:longint;
begin t:=i; i:=j; j:=t; end;
begin
    s:=0;m:=-maxlongint;
    while a<>b do begin
        if dep[a]<dep[b] then swap(a,b);
        if own[a]=own[b] then begin
            inc(s,w[a]);update(m,w[a]);
            a:=fa[a];
        end else begin
            if dep[own[a]]<dep[own[b]] then swap(a,b);
            inc(s,sum[a]);update(m,mun[a]);
            a:=fa[own[a]];
        end;
    end;
    inc(s,w[a]);update(m,w[a]);
end;
 
function readspace:char;var c:char;
begin
    read(c);read(c);readspace:=c;
    while c<>' ' do read(c);
end;
 
var n,i,x,y,que,s,m:longint; ch:char;
begin
    readln(n);limit:=trunc(sqrt(n));
    for i:=1 to n-1 do begin readln(x,y);push(ge[x],y);push(ge[y],x);end;
    for i:=1 to n do begin read(w[i]);own[i]:=i;end;build(1,0,1);
    for i:=1 to n do if own[i]=i then Dfs(i,0,-maxlongint);
    readln(que);for que:=1 to que do begin
        ch:=readspace;readln(x,y);
        if ch='H' then change(x,y) else begin
            get_answer(x,y,s,m);
            if ch='S' then writeln(s) else writeln(m);
        end;
    end;
end.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值