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.