1036: [ZJOI2008]树的统计Count - BZOJ

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 const

  2     maxn=30010;

  3 type

  4     node=record

  5       son:array[0..1]of longint;

  6       sum,max,left,right,mid:longint;

  7     end;

  8 var

  9     n,m,num,tot,xx,ll,rr,goal:longint;

 10     tree:array[0..maxn*2]of node;

 11     first,fa,dep,son,size,w,top,root:array[0..maxn]of longint;

 12     next,last:array[0..maxn*2]of longint;

 13 

 14 procedure insert(x,y:longint);

 15 begin

 16     inc(num);

 17     last[num]:=y;

 18     next[num]:=first[x];

 19     first[x]:=num;

 20 end;

 21 

 22 procedure dfs1(x,d,f:longint);

 23 var

 24     i:longint;

 25 begin

 26     dep[x]:=d;

 27     fa[x]:=f;

 28     size[x]:=1;

 29     i:=first[x];

 30     while i<>0 do

 31       begin

 32         if last[i]<>f then

 33         begin

 34           dfs1(last[i],d+1,x);

 35           if size[last[i]]>size[son[x]] then son[x]:=last[i];

 36           inc(size[x],size[last[i]]);

 37         end;

 38         i:=next[i];

 39       end;

 40 end;

 41 

 42 procedure build(l,r:longint);

 43 var

 44     now:longint;

 45 begin

 46     inc(tot);

 47     now:=tot; 

 48     with tree[now] do

 49       begin

 50         left:=l;

 51         right:=r;

 52         if l=r then exit;

 53         mid:=(l+r)>>1;

 54         son[0]:=tot+1;

 55         build(l,mid);

 56         son[1]:=tot+1;

 57         build(mid+1,r);

 58       end;

 59 end;

 60 

 61 procedure dfs2(x,t,ww:longint);

 62 var

 63     i:longint;

 64 begin

 65     w[x]:=ww;

 66     top[x]:=t;

 67     if son[x]=0 then

 68       begin

 69         root[x]:=tot+1;

 70         build(1,ww);

 71         exit;

 72       end

 73     else

 74       begin

 75         dfs2(son[x],t,ww+1);

 76         root[x]:=root[son[x]];

 77       end;

 78     i:=first[x];

 79     while i<>0 do

 80       begin

 81         if (last[i]<>fa[x]) and (last[i]<>son[x]) then dfs2(last[i],last[i],1);

 82         i:=next[i];

 83       end;

 84 end;

 85 

 86 procedure change(now:longint);

 87 begin

 88     with tree[now] do

 89       begin

 90         if left=right then

 91         begin

 92           sum:=goal;

 93           max:=goal;

 94           exit;

 95         end;

 96         if xx<=mid then change(son[0])

 97         else change(son[1]);

 98         if tree[son[0]].max>tree[son[1]].max then max:=tree[son[0]].max

 99         else max:=tree[son[1]].max;

100         sum:=tree[son[0]].sum+tree[son[1]].sum;

101       end;

102 end;

103 

104 function getsum(now:longint):longint;

105 begin

106     with tree[now] do

107       begin

108         if (ll<=left) and (rr>=right) then exit(sum);

109         if rr<=mid then exit(getsum(son[0]));

110         if ll>mid then exit(getsum(son[1]));

111         exit(getsum(son[0])+getsum(son[1]));

112       end;

113 end;

114 

115 function getmax(now:longint):longint;

116 var

117     s:longint;

118 begin

119     with tree[now] do

120       begin

121         if (ll<=left) and (rr>=right) then exit(max);

122         if rr<=mid then exit(getmax(son[0]));

123         if ll>mid then exit(getmax(son[1]));

124         getmax:=getmax(son[0]);

125         s:=getmax(son[1]);

126         if s>getmax then getmax:=s;

127       end;

128 end;

129 

130 procedure init;

131 var

132     i,x,y:longint;

133 begin

134     read(n);

135     for i:=1 to n-1 do

136       begin

137         read(x,y);

138         insert(x,y);

139         insert(y,x);

140       end;

141     dfs1(1,1,0);

142     dfs2(1,1,1);

143     for i:=1 to n do

144       begin

145         read(goal);

146         xx:=w[i];

147         change(root[i]);

148       end;

149 end;

150 

151 procedure work;

152 var

153     i,ans,s,x,y:longint;

154     s1,s2:char;

155 begin

156     read(m);

157     for i:=1 to m do

158       begin

159         read(s2);

160         while s2<>' ' do

161           begin

162             s1:=s2;

163             read(s2);

164           end;

165         read(x,y);

166         case s1 of

167           'E':begin

168             goal:=y;

169             xx:=w[x];

170             change(root[x]);

171           end;

172           'X':begin

173             ans:=-300000;

174             while top[x]<>top[y] do

175               begin

176                 if dep[top[x]]<dep[top[y]] then

177                 begin

178                   s:=x;x:=y;y:=s;

179                 end;

180                 ll:=1;

181                 rr:=w[x];

182                 s:=getmax(root[x]);

183                 if s>ans then ans:=s;

184                 x:=fa[top[x]];

185               end;

186             if dep[x]<dep[y] then

187             begin

188               s:=x;x:=y;y:=s;

189             end;

190             ll:=w[y];

191             rr:=w[x];

192             s:=getmax(root[x]);

193             if s>ans then ans:=s;

194             writeln(ans);

195           end;

196           'M':begin

197             ans:=0;

198             while top[x]<>top[y] do

199               begin

200                 if dep[top[x]]<dep[top[y]] then

201                 begin

202                   s:=x;x:=y;y:=s;

203                 end;

204                 ll:=1;

205                 rr:=w[x];

206                 inc(ans,getsum(root[x]));

207                 x:=fa[top[x]];

208               end;

209             if dep[x]<dep[y] then

210             begin

211               s:=x;x:=y;y:=s;

212             end;

213             ll:=w[y];

214             rr:=w[x];

215             inc(ans,getsum(root[x]));

216             writeln(ans);

217           end;

218         end;

219       end;

220 end;

221 

222 begin

223     init;

224     work;

225 end.
View Code

 

你可能感兴趣的:(count)