首页 > 代码库 > 【BZOJ1036】树的统计Count(树链剖分)

【BZOJ1036】树的统计Count(树链剖分)

题意:一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作:

I. CHANGE u t : 把结点u的权值改为t

II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值

I

II. QSUM u v: 询问从点u到点v的路径上的节点的权值和

注意:从点u到点v的路径上的节点包括u和v本身

1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

 

思路:树链剖分,单点修改,区间查询和与最大值。

  1 var t1,t2,next,vet,head,dep,flag,tid,fa,top,size,id,son,a
  2    :array[1..200000]of longint;
  3     n,m,i,j,k,k1,t,x,y,tot,time,q,len,f:longint;
  4     ch:string;
  5 
  6 procedure add(a,b:longint);
  7 begin
  8  inc(tot);
  9  next[tot]:=head[a];
 10  vet[tot]:=b;
 11  head[a]:=tot;
 12 end;
 13 
 14 function max(x,y:longint):longint;
 15 begin
 16  if x>y then exit(x);
 17  exit(y);
 18 end;
 19 
 20 procedure dfs1(u,fath,depth:longint);
 21 var e,v,maxsize:longint;
 22 begin
 23  flag[u]:=1; dep[u]:=depth; fa[u]:=fath;
 24  e:=head[u];
 25  flag[u]:=1; size[u]:=1;
 26  maxsize:=0; son[u]:=0;
 27  while e<>0 do
 28  begin
 29   v:=vet[e];
 30   if flag[v]=0 then
 31   begin
 32   // h[e]:=1;
 33    dfs1(v,u,depth+1);
 34    size[u]:=size[u]+size[v];
 35    if size[v]>maxsize then
 36    begin
 37     maxsize:=size[v];
 38     son[u]:=v;
 39    end;
 40   end;
 41   e:=next[e];
 42  end;
 43 end;
 44 
 45 procedure dfs2(u,ance:longint);
 46 var e,v:longint;
 47 begin
 48  flag[u]:=1; inc(time); tid[u]:=time; id[time]:=u; top[u]:=ance;
 49  if son[u]>0 then dfs2(son[u],ance);
 50  e:=head[u];
 51  while e<>0 do
 52  begin
 53   v:=vet[e];
 54   if flag[v]=0 then dfs2(v,v);
 55   e:=next[e];
 56  end;
 57 end;
 58 
 59 procedure build(l,r,p:longint);
 60 var mid:longint;
 61 begin
 62  if l=r then
 63  begin
 64   t1[p]:=a[id[l]];
 65   t2[p]:=a[id[l]];
 66   exit;
 67  end;
 68  mid:=(l+r)>>1;
 69  build(l,mid,p<<1);
 70  build(mid+1,r,p<<1+1);
 71  t1[p]:=max(t1[p<<1],t1[p<<1+1]);
 72  t2[p]:=t2[p<<1]+t2[p<<1+1];
 73 end;
 74 
 75 procedure update(l,r,x,v,p:longint);
 76 var mid:longint;
 77 begin
 78  if l=r then
 79  begin
 80   t1[p]:=v; t2[p]:=v;
 81   exit;
 82  end;
 83  mid:=(l+r)>>1;
 84  if x<=mid then update(l,mid,x,v,p<<1);
 85  if x>mid then update(mid+1,r,x,v,p<<1+1);
 86  t1[p]:=max(t1[p<<1],t1[p<<1+1]);
 87  t2[p]:=t2[p<<1]+t2[p<<1+1];
 88 end;
 89 
 90 function querymax(l,r,x,y,p:longint):longint;
 91 var mid,t:longint;
 92 begin
 93  if (l=x)and(r=y) then exit(t1[p]);
 94  mid:=(l+r)>>1;
 95  t:=-maxlongint;
 96  if y<=mid then t:=querymax(l,mid,x,y,p<<1)
 97   else if x>mid then t:=querymax(mid+1,r,x,y,p<<1+1)
 98   else t:=max(querymax(l,mid,x,mid,p<<1),querymax(mid+1,r,mid+1,y,p<<1+1));
 99  exit(t);
100 end;
101 
102 function querysum(l,r,x,y,p:longint):longint;
103 var mid,t:longint;
104 begin
105  if (l=x)and(r=y) then exit(t2[p]);
106  mid:=(l+r)>>1;
107  t:=0;
108  if y<=mid then t:=querysum(l,mid,x,y,p<<1)
109   else if x>mid then t:=querysum(mid+1,r,x,y,p<<1+1)
110    else t:=querysum(l,mid,x,mid,p<<1)+querysum(mid+1,r,mid+1,y,p<<1+1);
111  exit(t);
112 end;
113 
114 procedure swap(var x,y:longint);
115 var t:longint;
116 begin
117  t:=x; x:=y; y:=t;
118 end;
119 
120 function askmax(x,y:longint):longint;
121 var f1,f2,t:longint;
122 begin
123  t:=-maxlongint;
124  f1:=top[x]; f2:=top[y];
125  while f1<>f2 do
126  begin
127   if dep[f1]<dep[f2] then
128   begin
129    swap(f1,f2); swap(x,y);
130   end;
131   t:=max(t,querymax(1,n,tid[f1],tid[x],1));
132   x:=fa[f1]; f1:=top[x];
133  end;
134  if dep[x]>dep[y] then swap(x,y);
135  t:=max(t,querymax(1,n,tid[x],tid[y],1));
136  exit(t);
137 end;
138 
139 function asksum(x,y:longint):longint;
140 var f1,f2,t:longint;
141 begin
142  t:=0;
143  f1:=top[x]; f2:=top[y];
144  while f1<>f2 do
145  begin
146   if dep[f1]<dep[f2] then
147   begin
148    swap(f1,f2); swap(x,y);
149   end;
150   t:=t+querysum(1,n,tid[f1],tid[x],1);
151   x:=fa[f1]; f1:=top[x];
152  end;
153  if dep[x]>dep[y] then swap(x,y);
154  t:=t+querysum(1,n,tid[x],tid[y],1);
155  exit(t);
156 end;
157 
158 begin
159  //assign(input,bzoj1036.in); reset(input);
160  //assign(output,bzoj1036.out); rewrite(output);
161  readln(n);
162  for i:=1 to n-1 do
163  begin
164   readln(x,y);
165   add(x,y);
166   add(y,x);
167  end;
168  for i:=1 to n do read(a[i]);
169  dfs1(1,-1,1);
170  fillchar(flag,sizeof(flag),0);
171  dfs2(1,1);
172  fillchar(t1,sizeof(t1),$8f);
173  build(1,n,1);
174  readln(q);
175  for i:=1 to q do
176  begin
177   readln(ch);
178   x:=0; y:=0;
179   for j:=1 to length(ch) do
180    if ch[j]=  then break;
181   while ch[j]=  do inc(j);
182   f:=1;
183   while ch[j]<>  do
184   begin
185   // if ch[j]=- then f:=-1;
186    if (ch[j]>=0)and(ch[j]<=9) then x:=x*10+ord(ch[j])-ord(0);
187    inc(j);
188   end;
189 
190   while ch[j]=  do inc(j);
191   while (j<=length(ch))and(ch[j]<> ) do
192   begin
193    if ch[j]=- then f:=-1;
194    if (ch[j]>=0)and(ch[j]<=9) then y:=y*10+ord(ch[j])-ord(0);
195    inc(j);
196   end;
197   if f=-1 then y:=-y;
198 
199 
200 
201   if ch[1]=C then update(1,n,tid[x],y,1);
202   if (ch[1]=Q)and(ch[2]=M) then writeln(askmax(x,y));
203   if (ch[1]=Q)and(ch[2]=S) then writeln(asksum(x,y));
204  {  if ch[1]=‘C‘ then
205   begin
206    delete(ch,1,7);
207    val(copy(ch,1,pos(‘ ‘,ch)-1),x);
208    val(copy(ch,pos(‘ ‘,ch)+1,length(ch)-pos(‘ ‘,ch)),y);
209    update(1,n,tid[x],y,1);
210   end
211    else if ch[2]=‘M‘ then
212    begin
213     delete(ch,1,5);
214     val(copy(ch,1,pos(‘ ‘,ch)-1),x);
215     val(copy(ch,pos(‘ ‘,ch)+1,length(ch)-pos(‘ ‘,ch)),y);
216     writeln(askmax(x,y));
217    end
218     else
219     begin
220      delete(ch,1,5);
221      val(copy(ch,1,pos(‘ ‘,ch)-1),x);
222      val(copy(ch,pos(‘ ‘,ch)+1,length(ch)-pos(‘ ‘,ch)),y);
223      writeln(asksum(x,y));
224 
225     end;    }
226 
227  end;
228  //close(input);
229  //close(output);
230 end.

 

【BZOJ1036】树的统计Count(树链剖分)