首页 > 代码库 > ZJ2008树的统计(树链剖分)

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.


                      

作为以后的模版!