bzoj1036 [ZJOI2008]树的统计Count
Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身
Input
输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
Output
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
Sample Input
4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4
Sample Output
4
1
2
2
10
6
5
6
5
16
1
2
2
10
6
5
6
5
16
树链剖分裸题,然而写的时候发现自己忘了线段树的单点修改只会区间修改
1 program rrr(input,output); 2 type 3 tree=record 4 l,r,sum,max:longint; 5 end; 6 pointer=^nodetype; 7 nodetype=record 8 t:longint; 9 next:pointer; 10 end; 11 var 12 a:array[0..4*30030]of tree; 13 b:array[0..30030]of pointer; 14 p:pointer; 15 q,dep,belong,head,idx,father,siz,num:array[0..30030]of longint; 16 v:array[0..30030]of boolean; 17 n,m,i,j,x,y,h,t,cnt,tot,ans:longint; 18 s:string; 19 function max(a,b:longint):longint; 20 begin 21 if a>b then exit(a) else exit(b); 22 end; 23 procedure add(x,y:longint); 24 begin 25 new(p);p^.t:=y;p^.next:=b[x];b[x]:=p; 26 end; 27 procedure bfs; 28 begin 29 fillchar(v,sizeof(v),false); 30 h:=0;t:=1;q[1]:=1;dep[1]:=0;v[1]:=true; 31 while h<t do 32 begin 33 inc(h);p:=b[q[h]]; 34 while p<>nil do 35 begin 36 if not v[p^.t] then 37 begin 38 inc(t);q[t]:=p^.t;v[p^.t]:=true; 39 dep[p^.t]:=dep[q[h]]+1;father[p^.t]:=q[h]; 40 end; 41 p:=p^.next; 42 end; 43 end; 44 for i:=1 to n do siz[i]:=1; 45 for i:=n downto 2 do inc(siz[father[q[i]]],siz[q[i]]); 46 end; 47 procedure dfs(k:longint); 48 var 49 p:pointer; 50 i,max:longint; 51 begin 52 if siz[k]=1 then exit; 53 p:=b[k];max:=0; 54 while p<>nil do begin if p^.t<>father[k] then if siz[p^.t]>max then begin max:=siz[p^.t];i:=p^.t; end;p:=p^.next; end; 55 belong[i]:=belong[k];inc(cnt);idx[i]:=cnt; 56 dfs(i); 57 if siz[k]=2 then exit; 58 p:=b[k]; 59 while p<>nil do 60 begin 61 if (p^.t<>father[k]) and (p^.t<>i) then 62 begin 63 inc(cnt);idx[p^.t]:=cnt; 64 inc(tot);head[tot]:=p^.t;belong[p^.t]:=tot; 65 dfs(p^.t); 66 end; 67 p:=p^.next; 68 end; 69 end; 70 procedure build(k,l,r:longint); 71 var 72 mid,i:longint; 73 begin 74 a[k].l:=l;a[k].r:=r; 75 if l=r then begin a[k].sum:=num[l];a[k].max:=num[l];exit; end; 76 mid:=(l+r)>>1;i:=k<<1; 77 build(i,l,mid);build(i+1,mid+1,r); 78 a[k].max:=max(a[i].max,a[i+1].max);a[k].sum:=a[i].sum+a[i+1].sum; 79 end; 80 procedure work; 81 begin 82 j:=pos(' ',s); 83 val(copy(s,1,j-1),x); 84 delete(s,1,j);val(s,y); 85 end; 86 procedure change(k:longint); 87 var 88 mid,i:longint; 89 begin 90 if a[k].l=a[k].r then begin a[k].max:=y;a[k].sum:=y;exit; end; 91 mid:=(a[k].l+a[k].r)>>1;i:=k<<1; 92 if x<=mid then change(i) else change(i+1); 93 a[k].sum:=a[i].sum+a[i+1].sum;a[k].max:=max(a[i].max,a[i+1].max); 94 end; 95 function askmax(k,x,y:longint):longint; 96 var 97 mid,i:longint; 98 begin 99 if (x<=a[k].l) and (a[k].r<=y) then exit(a[k].max); 100 mid:=(a[k].l+a[k].r)>>1;i:=k<<1; 101 askmax:=-30000; 102 if x<=mid then askmax:=askmax(i,x,y); 103 if mid<y then askmax:=max(askmax,askmax(i+1,x,y)); 104 end; 105 function asksum(k,x,y:longint):longint; 106 var 107 mid,i:longint; 108 begin 109 if (x<=a[k].l) and (a[k].r<=y) then exit(a[k].sum); 110 mid:=(a[k].l+a[k].r)>>1;i:=k<<1; 111 asksum:=0; 112 if x<=mid then asksum:=asksum(i,x,y); 113 if mid<y then asksum:=asksum+asksum(i+1,x,y); 114 end; 115 function ask1:longint; 116 begin 117 ans:=-30000; 118 while belong[x]<>belong[y] do 119 if dep[head[belong[x]]]>dep[head[belong[y]]] then begin ans:=max(ans,askmax(1,idx[head[belong[x]]],idx[x]));x:=father[head[belong[x]]]; end 120 else begin ans:=max(ans,askmax(1,idx[head[belong[y]]],idx[y]));y:=father[head[belong[y]]]; end; 121 if dep[x]>dep[y] then exit(max(ans,askmax(1,idx[y],idx[x]))) 122 else exit(max(ans,askmax(1,idx[x],idx[y]))); 123 end; 124 function ask2:longint; 125 begin 126 ans:=0; 127 while belong[x]<>belong[y] do 128 if dep[head[belong[x]]]>dep[head[belong[y]]] then begin ans:=ans+asksum(1,idx[head[belong[x]]],idx[x]);x:=father[head[belong[x]]]; end 129 else begin ans:=ans+asksum(1,idx[head[belong[y]]],idx[y]);y:=father[head[belong[y]]]; end; 130 if dep[x]>dep[y] then exit(ans+asksum(1,idx[y],idx[x])) 131 else exit(ans+asksum(1,idx[x],idx[y])); 132 end; 133 begin 134 assign(input,'r.in');assign(output,'r.out');reset(input);rewrite(output); 135 readln(n); 136 for i:=1 to n do b[i]:=nil; 137 for i:=1 to n-1 do begin readln(x,y);add(x,y);add(y,x); end; 138 bfs; 139 belong[1]:=1;head[1]:=1;tot:=1;cnt:=1;idx[1]:=1; 140 dfs(1); 141 for i:=1 to n do read(num[idx[i]]); 142 build(1,1,n); 143 readln(m); 144 for i:=1 to m do 145 begin 146 readln(s); 147 if s[2]='M' then begin delete(s,1,5);work;writeln(ask1); end; 148 if s[2]='S' then begin delete(s,1,5);work;writeln(ask2); end; 149 if s[2]='H' then begin delete(s,1,7);work;x:=idx[x];change(1); end; 150 end; 151 close(input);close(output); 152 end.
2017.3.29+
这个代码是以前写的,用的还是指针存树+dfs初始化
刚刚又复习了一下这题,用现在的风格写的,主要区别是数组模拟邻接表存树和非递归初始化。
传送门: