http://www.cnblogs.com/BLADEVIL/p/3479713.html

这个大神写的特别好……难得的是还是p党(感动)

 

[ZJOI2008]树的统计Count

线段树只需要单点修改……

type

  arr1=record

    toward,next:longint;

  end;

  arr2=record

    left,right,max,sum:longint;

  end;

 

 

const

  mm=500000;

var

  tree:array[0..mm]of arr2;

  edge:array[0..mm]of arr1;

  first,num,value,top,hash,fa,size,maxson,dep:array[0..mm]of longint;

  chose:array[0..mm]of boolean;

  total,tot:longint;

 

function max(x,y:longint):longint;

begin

  if x<y then exit(y);

  exit(x);

end;

 

procedure swap(var x,y:longint);

var

  i:longint;

begin

  i:=x;

  x:=y;

  y:=i;

end;

 

procedure update(x:longint);

begin

  tree[x].sum:=tree[x<<1].sum+tree[x<<1+1].sum;

  tree[x].max:=max(tree[x<<1].max,tree[x<<1+1].max);

end;

 

procedure addedge(j,k:longint);

begin

  inc(total);

  edge[total].toward:=k;

  edge[total].next:=first[j];

  first[j]:=total;

end;

 

procedure dfs(x:longint);

var

  i,too:longint;

begin

  chose[x]:=false;

  i:=first[x];

  size[x]:=1;

  maxson[x]:=0;

  while i<>0 do begin

    too:=edge[i].toward;

    if chose[too] then begin

      fa[too]:=x;

      dfs(too);

      inc(size[x],size[too]);

      if size[too]>size[maxson[x]] then maxson[x]:=too;

    end;

    i:=edge[i].next;

  end;

end;

 

procedure make(x,y,depth:longint);

var

  i,too:longint;

begin

  inc(tot);

  num[x]:=tot;

  hash[tot]:=value[x];

  chose[x]:=false;

  top[x]:=y;

  dep[x]:=depth;

  if maxson[x]<>0 then make(maxson[x],y,depth);

  i:=first[x];

  while i<>0 do begin

    too:=edge[i].toward;

    if (chose[too]) and (too<>maxson[x]) then make(too,too,depth+1);

    i:=edge[i].next;

  end;

end;

 

procedure build(x,l,r:longint);

var

  mid:longint;

begin

  tree[x].left:=l;

  tree[x].right:=r;

  if l=r then begin

    tree[x].sum:=hash[l];

    tree[x].max:=hash[l];

    exit;

  end;

  mid:=(l+r)>>1;

  build(x<<1,l,mid);

  build(x<<1+1,mid+1,r);

  update(x);

end;

 

function askmax(x,ll,rr:longint):longint;

var

  mid:longint;

begin

  if (tree[x].left=ll) and (tree[x].right=rr) then exit(tree[x].max);

  mid:=(tree[x].left+tree[x].right)>>1;

  if ll>mid

    then exit(askmax(x<<1+1,ll,rr))

    else

      if rr<=mid then exit(askmax(x<<1,ll,rr))

      else exit(max(askmax(x<<1,ll,mid),askmax(x<<1+1,mid+1,rr)));

end;

 

function asksum(x,ll,rr:longint):longint;

var

  mid:longint;

begin

  if (tree[x].left=ll) and (tree[x].right=rr) then exit(tree[x].sum);

  mid:=(tree[x].left+tree[x].right)>>1;

  if ll>mid then exit(asksum(x<<1+1,ll,rr))

  else

    if rr<=mid then exit(asksum(x<<1,ll,rr))

    else exit(asksum(x<<1,ll,mid)+asksum(x<<1+1,mid+1,rr));

end;

 

procedure change(x,u,z:longint);

var

  mid:longint;

begin

  if (tree[x].left=u) and (tree[x].right=u) then begin

    tree[x].sum:=z;

    tree[x].max:=z;

    exit;

  end;

  mid:=(tree[x].left+tree[x].right)>>1;

  if u>mid then change(x<<1+1,u,z)

  else change(x<<1,u,z);

  update(x);

end;

 

procedure querymax(x,y:longint);

var

  ans:longint;

begin

  ans:=-100000000;

  if dep[x]>dep[y] then swap(x,y);

  while dep[x]<dep[y] do begin

    ans:=max(ans,askmax(1,num[top[y]],num[y]));

    y:=fa[top[y]];

  end;

  while top[x]<>top[y] do begin

    ans:=max(ans,max(askmax(1,num[top[x]],num[x]),askmax(1,num[top[y]],num[y])));

    x:=fa[top[x]];

    y:=fa[top[y]];

  end;

  x:=num[x];

  y:=num[y];

  if x>y then swap(x,y);

  ans:=max(ans,askmax(1,x,y));

  writeln(ans);

end;

 

procedure querysum(x,y:longint);

var

  ans:longint;

begin

  ans:=0;

  if dep[x]>dep[y] then swap(x,y);

  while dep[x]<dep[y] do begin

    ans:=ans+asksum(1,num[top[y]],num[y]);

    y:=fa[top[y]];

  end;

  while top[x]<>top[y] do begin

    ans:=ans+asksum(1,num[top[x]],num[x])+asksum(1,num[top[y]],num[y]);

    x:=fa[top[x]];

    y:=fa[top[y]];

  end;

  x:=num[x];

  y:=num[y];

  if x>y then swap(x,y);

  ans:=ans+asksum(1,x,y);

  writeln(ans);

end;

 

procedure into;

var

  i,j,k,n:longint;

begin

  readln(n);

  total:=0;

  tot:=0;

  fillchar(first,sizeof(first),0);

  for i:=1 to n-1 do begin

    readln(j,k);

    addedge(j,k);

    addedge(k,j);

  end;

  for i:=1 to n do read(value[i]);

  readln;

  fillchar(size,sizeof(size),0);

  fillchar(chose,sizeof(chose),true);

  dfs(1);

  fillchar(chose,sizeof(chose),true);

  make(1,1,1);

  build(1,1,n);

end;

 

 

procedure work;

var

  m,j,k:longint;

  ch:char;

begin

  readln(m);

  while m>0 do begin

    dec(m);

    read(ch);

    if ch='Q' then begin

      read(ch);

      if ch='M' then begin

        repeat

          read(ch);

        until ch=' ';

        readln(j,k);

        querymax(j,k);

      end

      else begin

        repeat

          read(ch);

        until ch=' ';

        readln(j,k);

        querysum(j,k);

      end;

    end

    else begin

      repeat

        read(ch);

      until ch=' ';

      readln(j,k);

      change(1,num[j],k);

    end;

  end;

end;

 

 

begin

  into;

  work;

  readln;

  readln;

end.
View Code

相关文章:

猜你喜欢
  • 2022-01-06
  • 2021-11-20
  • 2021-08-09
  • 2021-04-05
相关资源
相似解决方案