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
没什么可说的,就是复习一下树链剖分模板。
以前做过,那是还是用指针存树的,也是dfs的。
现在写的是数组模拟邻接表,以及非递归的预处理。
这个非递归预处理可以使子树和链都在一起,也可以只保证链在一起,这题没有子树操作,只要后者即可,但也写了下使子树在一起的代码。
先是只保证链在一起的代码:
1 program rrr(input,output); 2 const 3 inf=123456789; 4 type 5 treetype=record 6 l,r,max,sum:longint; 7 end; 8 etype=record 9 t,next:longint; 10 end; 11 var 12 a:array[0..120012]of treetype; 13 b,c,father,siz,son,ss,idx,head,q,dep:array[0..30030]of longint; 14 e:array[0..60060]of etype; 15 n,m,i,j,x,y,cnt,h,t,ans:longint; 16 s:string; 17 function max(a,b:longint):longint; 18 begin 19 if a>b then exit(a) else exit(b); 20 end; 21 procedure add(x,y:longint); 22 begin 23 inc(cnt);e[cnt].t:=y;e[cnt].next:=c[x];c[x]:=cnt; 24 end; 25 procedure work; 26 begin 27 j:=pos(' ',s);val(copy(s,1,j-1),x);delete(s,1,j);val(s,y); 28 end; 29 procedure prepare; 30 begin 31 h:=0;t:=1;q[1]:=1;father[1]:=0;dep[1]:=1; 32 while h<t do 33 begin 34 inc(h); 35 i:=c[q[h]]; 36 while i<>0 do 37 begin 38 if e[i].t<>father[q[h]] then 39 begin 40 father[e[i].t]:=q[h];dep[e[i].t]:=dep[q[h]]+1; 41 inc(t);q[t]:=e[i].t; 42 end; 43 i:=e[i].next; 44 end; 45 end; 46 fillchar(son,sizeof(son),0);fillchar(ss,sizeof(ss),0); 47 for i:=1 to n do siz[i]:=1; 48 for i:=n downto 2 do 49 begin 50 inc(siz[father[q[i]]],siz[q[i]]); 51 if siz[q[i]]>ss[father[q[i]]] then 52 begin ss[father[q[i]]]:=siz[q[i]];son[father[q[i]]]:=q[i]; end; 53 end; 54 cnt:=0;fillchar(idx,sizeof(idx),0); 55 for i:=1 to n do 56 if idx[q[i]]=0 then 57 begin 58 j:=q[i]; 59 while j<>0 do begin inc(cnt);idx[j]:=cnt;head[j]:=q[i];j:=son[j]; end; 60 end; 61 end; 62 procedure build(k,l,r:longint); 63 var 64 mid,i:longint; 65 begin 66 a[k].l:=l;a[k].r:=r; 67 if l=r then begin a[k].max:=b[l];a[k].sum:=b[l];exit; end; 68 mid:=(l+r)>>1;i:=k+k; 69 build(i,l,mid); 70 build(i+1,mid+1,r); 71 a[k].max:=max(a[i].max,a[i+1].max); 72 a[k].sum:=a[i].sum+a[i+1].sum; 73 end; 74 procedure change(k,x,y:longint); 75 var 76 mid,i:longint; 77 begin 78 if a[k].l=a[k].r then begin a[k].sum:=y;a[k].max:=y;exit end; 79 mid:=(a[k].l+a[k].r)>>1;i:=k+k; 80 if x<=mid then change(i,x,y) else change(i+1,x,y); 81 a[k].max:=max(a[i].max,a[i+1].max); 82 a[k].sum:=a[i].sum+a[i+1].sum; 83 end; 84 function askmax(k,x,y:longint):longint; 85 var 86 mid,ans:longint; 87 begin 88 if (x<=a[k].l) and (a[k].r<=y) then exit(a[k].max); 89 mid:=(a[k].l+a[k].r)>>1; 90 ans:=-inf; 91 if x<=mid then ans:=askmax(k+k,x,y); 92 if mid<y then ans:=max(ans,askmax(k+k+1,x,y)); 93 exit(ans); 94 end; 95 function asksum(k,x,y:longint):longint; 96 var 97 mid,ans:longint; 98 begin 99 if (x<=a[k].l) and (a[k].r<=y) then exit(a[k].sum); 100 mid:=(a[k].l+a[k].r)>>1; 101 ans:=0; 102 if x<=mid then ans:=asksum(k+k,x,y); 103 if mid<y then ans:=ans+asksum(k+k+1,x,y); 104 exit(ans); 105 end; 106 procedure qmax; 107 begin 108 ans:=-inf; 109 while head[x]<>head[y] do 110 if dep[head[x]]>dep[head[y]] then 111 begin 112 ans:=max(ans,askmax(1,idx[head[x]],idx[x])); 113 x:=father[head[x]]; 114 end 115 else begin 116 ans:=max(ans,askmax(1,idx[head[y]],idx[y])); 117 y:=father[head[y]]; 118 end; 119 if dep[x]>dep[y] then ans:=max(ans,askmax(1,idx[y],idx[x])) 120 else ans:=max(ans,askmax(1,idx[x],idx[y])); 121 end; 122 procedure qsum; 123 begin 124 ans:=0; 125 while head[x]<>head[y] do 126 if dep[head[x]]>dep[head[y]] then 127 begin 128 ans:=ans+asksum(1,idx[head[x]],idx[x]); 129 x:=father[head[x]]; 130 end 131 else begin 132 ans:=ans+asksum(1,idx[head[y]],idx[y]); 133 y:=father[head[y]]; 134 end; 135 if dep[x]>dep[y] then ans:=ans+asksum(1,idx[y],idx[x]) 136 else ans:=ans+asksum(1,idx[x],idx[y]); 137 end; 138 begin 139 assign(input,'r.in');assign(output,'r.out');reset(input);rewrite(output); 140 readln(n); 141 fillchar(c,sizeof(c),0);cnt:=0; 142 for i:=1 to n-1 do begin readln(x,y);add(x,y);add(y,x); end; 143 prepare; 144 for i:=1 to n do read(b[idx[i]]); 145 build(1,1,n); 146 readln(m); 147 for i:=1 to m do 148 begin 149 readln(s); 150 if s[1]='C' then begin delete(s,1,7);work;change(1,idx[x],y); end 151 else if s[2]='M' then begin delete(s,1,5);work;qmax;writeln(ans); end 152 else begin delete(s,1,5);work;qsum;writeln(ans); end; 153 end; 154 close(input);close(output); 155 end.
然后是是子树也在一起的代码:
1 program rrr(input,output); 2 const 3 inf=123456789; 4 type 5 treetype=record 6 l,r,max,sum:longint; 7 end; 8 etype=record 9 t,next:longint; 10 end; 11 var 12 a:array[0..120012]of treetype; 13 b,c,father,siz,son,ss,idx,head,q,dep,ot:array[0..30030]of longint; 14 e:array[0..60060]of etype; 15 n,m,i,j,x,y,cnt,h,t,ans:longint; 16 s:string; 17 function max(a,b:longint):longint; 18 begin 19 if a>b then exit(a) else exit(b); 20 end; 21 procedure add(x,y:longint); 22 begin 23 inc(cnt);e[cnt].t:=y;e[cnt].next:=c[x];c[x]:=cnt; 24 end; 25 procedure work; 26 begin 27 j:=pos(' ',s);val(copy(s,1,j-1),x);delete(s,1,j);val(s,y); 28 end; 29 procedure prepare; 30 begin 31 h:=0;t:=1;q[1]:=1;father[1]:=0;dep[1]:=1; 32 while h<t do 33 begin 34 inc(h); 35 i:=c[q[h]]; 36 while i<>0 do 37 begin 38 if e[i].t<>father[q[h]] then 39 begin 40 father[e[i].t]:=q[h];dep[e[i].t]:=dep[q[h]]+1; 41 inc(t);q[t]:=e[i].t; 42 end; 43 i:=e[i].next; 44 end; 45 end; 46 fillchar(son,sizeof(son),0);fillchar(ss,sizeof(ss),0); 47 for i:=1 to n do siz[i]:=1; 48 for i:=n downto 2 do 49 begin 50 inc(siz[father[q[i]]],siz[q[i]]); 51 if siz[q[i]]>ss[father[q[i]]] then 52 begin ss[father[q[i]]]:=siz[q[i]];son[father[q[i]]]:=q[i]; end; 53 end; 54 fillchar(idx,sizeof(idx),0);ot[0]:=0; 55 for i:=1 to n do 56 if idx[q[i]]=0 then 57 begin 58 cnt:=ot[father[q[i]]];j:=q[i]; 59 while j<>0 do 60 begin 61 head[j]:=q[i]; 62 inc(cnt);idx[j]:=cnt; 63 ot[j]:=cnt;inc(ot[father[j]],siz[j]); 64 j:=son[j]; 65 end; 66 end; 67 end; 68 procedure build(k,l,r:longint); 69 var 70 mid,i:longint; 71 begin 72 a[k].l:=l;a[k].r:=r; 73 if l=r then begin a[k].max:=b[l];a[k].sum:=b[l];exit; end; 74 mid:=(l+r)>>1;i:=k+k; 75 build(i,l,mid); 76 build(i+1,mid+1,r); 77 a[k].max:=max(a[i].max,a[i+1].max); 78 a[k].sum:=a[i].sum+a[i+1].sum; 79 end; 80 procedure change(k,x,y:longint); 81 var 82 mid,i:longint; 83 begin 84 if a[k].l=a[k].r then begin a[k].sum:=y;a[k].max:=y;exit end; 85 mid:=(a[k].l+a[k].r)>>1;i:=k+k; 86 if x<=mid then change(i,x,y) else change(i+1,x,y); 87 a[k].max:=max(a[i].max,a[i+1].max); 88 a[k].sum:=a[i].sum+a[i+1].sum; 89 end; 90 function askmax(k,x,y:longint):longint; 91 var 92 mid,ans:longint; 93 begin 94 if (x<=a[k].l) and (a[k].r<=y) then exit(a[k].max); 95 mid:=(a[k].l+a[k].r)>>1; 96 ans:=-inf; 97 if x<=mid then ans:=askmax(k+k,x,y); 98 if mid<y then ans:=max(ans,askmax(k+k+1,x,y)); 99 exit(ans); 100 end; 101 function asksum(k,x,y:longint):longint; 102 var 103 mid,ans:longint; 104 begin 105 if (x<=a[k].l) and (a[k].r<=y) then exit(a[k].sum); 106 mid:=(a[k].l+a[k].r)>>1; 107 ans:=0; 108 if x<=mid then ans:=asksum(k+k,x,y); 109 if mid<y then ans:=ans+asksum(k+k+1,x,y); 110 exit(ans); 111 end; 112 procedure qmax; 113 begin 114 ans:=-inf; 115 while head[x]<>head[y] do 116 if dep[head[x]]>dep[head[y]] then 117 begin 118 ans:=max(ans,askmax(1,idx[head[x]],idx[x])); 119 x:=father[head[x]]; 120 end 121 else begin 122 ans:=max(ans,askmax(1,idx[head[y]],idx[y])); 123 y:=father[head[y]]; 124 end; 125 if dep[x]>dep[y] then ans:=max(ans,askmax(1,idx[y],idx[x])) 126 else ans:=max(ans,askmax(1,idx[x],idx[y])); 127 end; 128 procedure qsum; 129 begin 130 ans:=0; 131 while head[x]<>head[y] do 132 if dep[head[x]]>dep[head[y]] then 133 begin 134 ans:=ans+asksum(1,idx[head[x]],idx[x]); 135 x:=father[head[x]]; 136 end 137 else begin 138 ans:=ans+asksum(1,idx[head[y]],idx[y]); 139 y:=father[head[y]]; 140 end; 141 if dep[x]>dep[y] then ans:=ans+asksum(1,idx[y],idx[x]) 142 else ans:=ans+asksum(1,idx[x],idx[y]); 143 end; 144 begin 145 assign(input,'r.in');assign(output,'r.out');reset(input);rewrite(output); 146 readln(n); 147 fillchar(c,sizeof(c),0);cnt:=0; 148 for i:=1 to n-1 do begin readln(x,y);add(x,y);add(y,x); end; 149 prepare; 150 for i:=1 to n do read(b[idx[i]]); 151 build(1,1,n); 152 readln(m); 153 for i:=1 to m do 154 begin 155 readln(s); 156 if s[1]='C' then begin delete(s,1,7);work;change(1,idx[x],y); end 157 else if s[2]='M' then begin delete(s,1,5);work;qmax;writeln(ans); end 158 else begin delete(s,1,5);work;qsum;writeln(ans); end; 159 end; 160 close(input);close(output); 161 end.
其实大部分都是一模一样的,只是预处理不一样。