ZJ2008树的统计(树链剖分)


type node1=record
go,next:longint;end;
node2=record
l,r,mx,sum:longint;end;
var i,x,y,n,q,tmp,cnt,sz,code:longint;
ch,st:string;
fa:array[0..30001,0..15] of longint;
v,deep,son,head,pl,belong,vis:array[0..30001] of longint;
e:array[0..60001] of node1;
t:array[0..100001] of node2;
procedure insert(x,y:longint);
begin
inc(cnt);e[cnt].go:=y;e[cnt].next:=head[x];head[x]:=cnt;
inc(cnt);e[cnt].go:=x;e[cnt].next:=head[y];head[y]:=cnt;
end;
procedure dfs1(x:longint);
var i,j:longint;
begin
son[x]:=1;vis[x]:=1;
for i:=1 to 14 do
begin
if deep[x]<(1<<i) then break;
fa[x,i]:=fa[fa[x,i-1],i-1];
end;
i:=head[x];
while i<>0 do
begin
j:=e[i].go;
if vis[j]=0 then
begin
deep[j]:=deep[x]+1;
fa[j,0]:=x;
dfs1(j);
inc(son[x],son[j]);
end;
i:=e[i].next;
end;
end;
procedure dfs2(x,chain:longint);
var i,j,k:longint;
begin
k:=0;inc(sz);
pl[x]:=sz;belong[x]:=chain;
i:=head[x];
while i<>0 do
begin
j:=e[i].go;
if (deep[j]>deep[x]) and (son[j]>son[k]) then k:=j;
i:=e[i].next;
end;
if k=0 then exit;
dfs2(k,chain);
i:=head[x];
while i<>0 do
begin
j:=e[i].go;
if (deep[j]>deep[x]) and (k<>j) then
dfs2(j,j);
i:=e[i].next;
end;
end;
function lca(x,y:longint):longint;
var i,tmp:longint;
begin
if deep[x]<deep[y] then begin tmp:=x;x:=y;y:=tmp;end;
tmp:=deep[x]-deep[y];
for i:=0 to 14 do
if (tmp and (1<<i)<>0) then x:=fa[x,i];
for i:=14 downto 0 do
if fa[x,i]<>fa[y,i] then
begin
x:=fa[x,i];y:=fa[y,i];
end;
if x=y then exit(x) else exit(fa[x,0]);
end;
procedure build(x,y,k:longint);
var mid:longint;
begin
with t[k] do
begin
l:=x;r:=y;
if l=r then exit;
mid:=(l+r)>>1;
build(l,mid,k<<1);
build(mid+1,r,k<<1+1);
end;
end;
function max(x,y:longint):longint;
begin
if x>y then exit(x) else exit(y);
end;
procedure change(x,y,k:longint);
var mid:longint;
begin
with t[k] do
begin
if l=r then
begin sum:=y;mx:=y;exit;end;
mid:=(l+r)>>1;
if x<=mid then change(x,y,k<<1)
else change(x,y,k<<1+1);
sum:=t[k<<1].sum+t[k<<1+1].sum;
mx:=max(t[k<<1].mx,t[k<<1+1].mx);
end;
end;
function getsum(x,y,k:longint):longint;
var mid:longint;
begin
with t[k] do
begin
if (l=x) and (r=y) then exit(sum);
mid:=(l+r)>>1;
if x>mid then exit(getsum(x,y,k<<1+1))
else if y<=mid then exit((getsum(x,y,k<<1)))
else exit(getsum(x,mid,k<<1)+getsum(mid+1,y,k<<1+1));
end;
end;
function getmx(x,y,k:longint):longint;
var mid:longint;
begin
with t[k] do
begin
if (l=x) and (r=y) then exit(mx);
mid:=(l+r)>>1;
if x>mid then exit(getmx(x,y,k<<1+1))
else if y<=mid then exit(getmx(x,y,k<<1))
else exit(max(getmx(x,mid,k<<1),getmx(mid+1,y,k<<1+1)));
end;
end;
function solvesum(x,y:longint):longint;
var sum:longint;
begin
sum:=0;
while belong[x]<>belong[y] do
begin
inc(sum,getsum(pl[belong[x]],pl[x],1));
x:=fa[belong[x],0];
end;
inc(sum,getsum(pl[y],pl[x],1));
exit(sum);
end;
function solvemx(x,y:longint):longint;
var mx:longint;
begin
mx:=-maxlongint;
while belong[x]<>belong[y] do
begin
mx:=max(mx,getmx(pl[belong[x]],pl[x],1));
x:=fa[belong[x],0];
end;
mx:=max(mx,getmx(pl[y],pl[x],1));
exit(mx);
end;
procedure init;
begin
readln(n);
for i:=1 to n-1 do
begin
readln(x,y);insert(x,y);
end;
for i:=1 to n do read(v[i]);
end;
procedure solve;
begin
build(1,n,1);
for i:=1 to n do change(pl[i],v[i],1);
readln(q);
for i:=1 to q do
begin
readln(st);
ch:=copy(st,1,pos(‘ ‘,st)-1);
delete(st,1,pos(‘ ‘,st));
val(copy(st,1,pos(‘ ‘,st)-1),x,code);
delete(st,1,pos(‘ ‘,st));
val(st,y,code);
case ch of
‘CHANGE‘:begin
v[x]:=y;
change(pl[x],y,1);
end;
‘QMAX‘:begin
tmp:=lca(x,y);
writeln(max(solvemx(x,tmp),solvemx(y,tmp)));
end;
else begin
tmp:=lca(x,y);
writeln(solvesum(x,tmp)+solvesum(y,tmp)-v[tmp]);
end;
end;
end;
end;
begin
init;
dfs1(1);
dfs2(1,1);
solve;
end.

作为以后的模版!

时间: 2024-10-27 05:21:31

ZJ2008树的统计(树链剖分)的相关文章

kyeremal-bzoj1036[ZJOI2008]-树的统计count-树链剖分

bzoj1036[ZJOI2008]-树的统计count 1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 7567  Solved: 3109 [Submit][Status][Discuss] Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QM

树的统计Count---树链剖分

NEFU专项训练十和十一——树链剖分 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个整

zjoi 2008 树的统计——树链剖分

比较基础的一道树链剖分的题 大概还是得说说思路 树链剖分是将树剖成很多条链,比较常见的剖法是按儿子的size来剖分,剖分完后对于这课树的询问用线段树维护--比如求路径和的话--随着他们各自的链向上走,直至他们在同一条链上为止.比较像lca的方法,只不过这里是按链为单位,而且隔壁的SymenYang说可以用树链剖分做lca..吓哭 然后说说惨痛的调题经历:边表一定要开够啊! 不是n-1 而是2*(n-1)啊! 然后写变量时原始值和映射值要搞清楚啊! 不要搞错了! 还有就是下次求最小值一定看清下界是

BZOJ 1036 树的统计-树链剖分

[ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 12904 Solved: 5191[Submit][Status][Discuss]Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM

luoguP2590 [ZJOI2008]树的统计 [树链剖分] [TLE的LCT]

题目描述 一棵树上有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本身 输入输出格式 输入格式: 输入文件的第一行为一个整数n,表示节点的个数. 接下来n – 1行,每行2个整数a和b,表示节点a和节点b之

【BZOJ 1036】【ZJOI 2008】树的统计 树链剖分模板题

sth神犇的模板: //bzoj1036 题目:一个n个点的树每个点有一个权值,支持修改单点权值,求某两点路径上的点权和或最大点权. #include <cstdio> using namespace std; int pos[30001],f[30001],up[30001],son[30001],size[30001],a[80001],next[80001],last[30001],sum[100001],max[100001];//pos是指某点在线段树中的位置:f是父节点:up是所在

[JSOI2008][BZOJ1036] 树的统计 - 树链剖分

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 & Output Input 输入文件的第一行为一个整数n,表示节点的个数. 接下来n – 1行,每行2个整

[ZJOI2008]树的统计 (树链剖分)

题目描述 一棵树上有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本身 输入输出格式 输入格式: 输入文件的第一行为一个整数n,表示节点的个数. 接下来n – 1行,每行2个整数a和b,表示节点a和节点b之

bzoj1036 树的统计(树链剖分+线段树)

1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 15120  Solved: 6141[Submit][Status][Discuss] Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I

BZOJ 1036: [ZJOI2008]树的统计Count (树链剖分模板题)

1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 14982  Solved: 6081[Submit][Status][Discuss] Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I