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

Sample Output

4
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.

其实大部分都是一模一样的,只是预处理不一样。

posted @ 2017-03-29 23:17  Klaier  阅读(145)  评论(0编辑  收藏  举报