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
 
 
树链剖分裸题,然而写的时候发现自己忘了线段树的单点修改只会区间修改
  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初始化

刚刚又复习了一下这题,用现在的风格写的,主要区别是数组模拟邻接表存树和非递归初始化。

传送门:

http://www.cnblogs.com/Currier/p/6642442.html

posted @ 2017-02-10 22:28  Klaier  阅读(213)  评论(0编辑  收藏  举报