您的位置:首页 > 其它

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

2014-04-06 16:58 316 查看
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

裸树链剖分,我就不多说了,附入门教程

const
maxn=30010;
type
node=record
son:array[0..1]of longint;
sum,max,left,right,mid:longint;
end;
var
n,m,num,tot,xx,ll,rr,goal:longint;
tree:array[0..maxn*2]of node;
first,fa,dep,son,size,w,top,root:array[0..maxn]of longint;
next,last:array[0..maxn*2]of longint;

procedure insert(x,y:longint);
begin
inc(num);
last[num]:=y;
next[num]:=first[x];
first[x]:=num;
end;

procedure dfs1(x,d,f:longint);
var
i:longint;
begin
dep[x]:=d;
fa[x]:=f;
size[x]:=1;
i:=first[x];
while i<>0 do
begin
if last[i]<>f then
begin
dfs1(last[i],d+1,x);
if size[last[i]]>size[son[x]] then son[x]:=last[i];
inc(size[x],size[last[i]]);
end;
i:=next[i];
end;
end;

procedure build(l,r:longint);
var
now:longint;
begin
inc(tot);
now:=tot;
with tree[now] do
begin
left:=l;
right:=r;
if l=r then exit;
mid:=(l+r)>>1;
son[0]:=tot+1;
build(l,mid);
son[1]:=tot+1;
build(mid+1,r);
end;
end;

procedure dfs2(x,t,ww:longint);
var
i:longint;
begin
w[x]:=ww;
top[x]:=t;
if son[x]=0 then
begin
root[x]:=tot+1;
build(1,ww);
exit;
end
else
begin
dfs2(son[x],t,ww+1);
root[x]:=root[son[x]];
end;
i:=first[x];
while i<>0 do
begin
if (last[i]<>fa[x]) and (last[i]<>son[x]) then dfs2(last[i],last[i],1);
i:=next[i];
end;
end;

procedure change(now:longint);
begin
with tree[now] do
begin
if left=right then
begin
sum:=goal;
max:=goal;
exit;
end;
if xx<=mid then change(son[0])
else change(son[1]);
if tree[son[0]].max>tree[son[1]].max then max:=tree[son[0]].max
else max:=tree[son[1]].max;
sum:=tree[son[0]].sum+tree[son[1]].sum;
end;
end;

function getsum(now:longint):longint;
begin
with tree[now] do
begin
if (ll<=left) and (rr>=right) then exit(sum);
if rr<=mid then exit(getsum(son[0]));
if ll>mid then exit(getsum(son[1]));
exit(getsum(son[0])+getsum(son[1]));
end;
end;

function getmax(now:longint):longint;
var
s:longint;
begin
with tree[now] do
begin
if (ll<=left) and (rr>=right) then exit(max);
if rr<=mid then exit(getmax(son[0]));
if ll>mid then exit(getmax(son[1]));
getmax:=getmax(son[0]);
s:=getmax(son[1]);
if s>getmax then getmax:=s;
end;
end;

procedure init;
var
i,x,y:longint;
begin
read(n);
for i:=1 to n-1 do
begin
read(x,y);
insert(x,y);
insert(y,x);
end;
dfs1(1,1,0);
dfs2(1,1,1);
for i:=1 to n do
begin
read(goal);
xx:=w[i];
change(root[i]);
end;
end;

procedure work;
var
i,ans,s,x,y:longint;
s1,s2:char;
begin
read(m);
for i:=1 to m do
begin
read(s2);
while s2<>' ' do
begin
s1:=s2;
read(s2);
end;
read(x,y);
case s1 of
'E':begin
goal:=y;
xx:=w[x];
change(root[x]);
end;
'X':begin
ans:=-300000;
while top[x]<>top[y] do
begin
if dep[top[x]]<dep[top[y]] then
begin
s:=x;x:=y;y:=s;
end;
ll:=1;
rr:=w[x];
s:=getmax(root[x]);
if s>ans then ans:=s;
x:=fa[top[x]];
end;
if dep[x]<dep[y] then
begin
s:=x;x:=y;y:=s;
end;
ll:=w[y];
rr:=w[x];
s:=getmax(root[x]);
if s>ans then ans:=s;
writeln(ans);
end;
'M':begin
ans:=0;
while top[x]<>top[y] do
begin
if dep[top[x]]<dep[top[y]] then
begin
s:=x;x:=y;y:=s;
end;
ll:=1;
rr:=w[x];
inc(ans,getsum(root[x]));
x:=fa[top[x]];
end;
if dep[x]<dep[y] then
begin
s:=x;x:=y;y:=s;
end;
ll:=w[y];
rr:=w[x];
inc(ans,getsum(root[x]));
writeln(ans);
end;
end;
end;
end;

begin
init;
work;
end.


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: