ZJ2008树的统计(树链剖分)
type node1=record go,next:longint;end; node2=record l,r,mx,sum:longint;end; var i,x,y,n,q,tmp,cnt,sz,code:longint; ch,st:string; fa:array[0..30001,0..15] of longint; v,deep,son,head,pl,belong,vis:array[0..30001] of longint; e:array[0..60001] of node1; t:array[0..100001] of node2; procedure insert(x,y:longint); begin inc(cnt);e[cnt].go:=y;e[cnt].next:=head[x];head[x]:=cnt; inc(cnt);e[cnt].go:=x;e[cnt].next:=head[y];head[y]:=cnt; end; procedure dfs1(x:longint); var i,j:longint; begin son[x]:=1;vis[x]:=1; for i:=1 to 14 do begin if deep[x]<(1<<i) then break; fa[x,i]:=fa[fa[x,i-1],i-1]; end; i:=head[x]; while i<>0 do begin j:=e[i].go; if vis[j]=0 then begin deep[j]:=deep[x]+1; fa[j,0]:=x; dfs1(j); inc(son[x],son[j]); end; i:=e[i].next; end; end; procedure dfs2(x,chain:longint); var i,j,k:longint; begin k:=0;inc(sz); pl[x]:=sz;belong[x]:=chain; i:=head[x]; while i<>0 do begin j:=e[i].go; if (deep[j]>deep[x]) and (son[j]>son[k]) then k:=j; i:=e[i].next; end; if k=0 then exit; dfs2(k,chain); i:=head[x]; while i<>0 do begin j:=e[i].go; if (deep[j]>deep[x]) and (k<>j) then dfs2(j,j); i:=e[i].next; end; end; function lca(x,y:longint):longint; var i,tmp:longint; begin if deep[x]<deep[y] then begin tmp:=x;x:=y;y:=tmp;end; tmp:=deep[x]-deep[y]; for i:=0 to 14 do if (tmp and (1<<i)<>0) then x:=fa[x,i]; for i:=14 downto 0 do if fa[x,i]<>fa[y,i] then begin x:=fa[x,i];y:=fa[y,i]; end; if x=y then exit(x) else exit(fa[x,0]); end; procedure build(x,y,k:longint); var mid:longint; begin with t[k] do begin l:=x;r:=y; if l=r then exit; mid:=(l+r)>>1; build(l,mid,k<<1); build(mid+1,r,k<<1+1); end; end; function max(x,y:longint):longint; begin if x>y then exit(x) else exit(y); end; procedure change(x,y,k:longint); var mid:longint; begin with t[k] do begin if l=r then begin sum:=y;mx:=y;exit;end; mid:=(l+r)>>1; if x<=mid then change(x,y,k<<1) else change(x,y,k<<1+1); sum:=t[k<<1].sum+t[k<<1+1].sum; mx:=max(t[k<<1].mx,t[k<<1+1].mx); end; end; function getsum(x,y,k:longint):longint; var mid:longint; begin with t[k] do begin if (l=x) and (r=y) then exit(sum); mid:=(l+r)>>1; if x>mid then exit(getsum(x,y,k<<1+1)) else if y<=mid then exit((getsum(x,y,k<<1))) else exit(getsum(x,mid,k<<1)+getsum(mid+1,y,k<<1+1)); end; end; function getmx(x,y,k:longint):longint; var mid:longint; begin with t[k] do begin if (l=x) and (r=y) then exit(mx); mid:=(l+r)>>1; if x>mid then exit(getmx(x,y,k<<1+1)) else if y<=mid then exit(getmx(x,y,k<<1)) else exit(max(getmx(x,mid,k<<1),getmx(mid+1,y,k<<1+1))); end; end; function solvesum(x,y:longint):longint; var sum:longint; begin sum:=0; while belong[x]<>belong[y] do begin inc(sum,getsum(pl[belong[x]],pl[x],1)); x:=fa[belong[x],0]; end; inc(sum,getsum(pl[y],pl[x],1)); exit(sum); end; function solvemx(x,y:longint):longint; var mx:longint; begin mx:=-maxlongint; while belong[x]<>belong[y] do begin mx:=max(mx,getmx(pl[belong[x]],pl[x],1)); x:=fa[belong[x],0]; end; mx:=max(mx,getmx(pl[y],pl[x],1)); exit(mx); end; procedure init; begin readln(n); for i:=1 to n-1 do begin readln(x,y);insert(x,y); end; for i:=1 to n do read(v[i]); end; procedure solve; begin build(1,n,1); for i:=1 to n do change(pl[i],v[i],1); readln(q); for i:=1 to q do begin readln(st); ch:=copy(st,1,pos(' ',st)-1); delete(st,1,pos(' ',st)); val(copy(st,1,pos(' ',st)-1),x,code); delete(st,1,pos(' ',st)); val(st,y,code); case ch of 'CHANGE':begin v[x]:=y; change(pl[x],y,1); end; 'QMAX':begin tmp:=lca(x,y); writeln(max(solvemx(x,tmp),solvemx(y,tmp))); end; else begin tmp:=lca(x,y); writeln(solvesum(x,tmp)+solvesum(y,tmp)-v[tmp]); end; end; end; end; begin init; dfs1(1); dfs2(1,1); solve; end.
作为以后的模版!