树链剖分的基本题
详细介绍在http://blog.sina.com.cn/s/blog_7a1746820100wp67.html
通过树链剖分我们就可以在树上做线段树操作,完成解答

 const inf=;
type node=record
po,next:longint;
end;
point=record
max,sum:longint;
end; var tree:array[..] of point;
size,d,fa,p,b,c,top:array[..] of longint;
w:array[..] of node;
len,i,n,m,x,y,t:longint;
ch:char;
s:string; function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end; procedure update(i:longint);
begin
tree[i].sum:=tree[i*].sum+tree[i*+].sum;
tree[i].max:=max(tree[i*].max,tree[i*+].max);
end; procedure swap(var a,b:longint);
var c:longint;
begin
c:=a;
a:=b;
b:=c;
end; procedure add(x,y:longint);
begin
inc(len);
w[len].po:=y;
w[len].next:=p[x];
p[x]:=len;
end; procedure dfs1(x:longint); //预处理
var i,y:longint;
begin
i:=p[x];
size[x]:=;
while i<> do
begin
y:=w[i].po;
if fa[x]<>y then
begin
fa[y]:=x;
d[y]:=d[x]+;
dfs1(y);
size[x]:=size[x]+size[y];
end;
i:=w[i].next;
end;
end; procedure dfs2(x:longint);
var i,y,q:longint;
begin
i:=p[x];
inc(t);
c[x]:=t;
q:=;
while i<> do
begin
y:=w[i].po;
if (c[y]=) and (size[q]<size[y]) then q:=y;
i:=w[i].next;
end;
if q<> then
begin
top[q]:=top[x]; //重儿子先访问
dfs2(q);
end;
i:=p[x]; //然后访问轻儿子
while i<> do
begin
y:=w[i].po;
if c[y]= then
begin
top[y]:=y;
dfs2(y);
end;
i:=w[i].next;
end;
end; procedure build(i,l,r:longint);
var m:longint;
begin
if l=r then
begin
tree[i].sum:=b[l];
tree[i].max:=b[l];
end
else begin
m:=(l+r) shr ;
build(i*,l,m);
build(i*+,m+,r);
update(i);
end;
end; procedure add(i,l,r:longint);
var m:longint;
begin
if l=r then
begin
tree[i].sum:=y;
tree[i].max:=y;
end
else begin
m:=(l+r) shr ;
if x<=m then add(i*,l,m) else add(i*+,m+,r);
update(i);
end;
end; function getmax(i,l,r,x,y:longint):longint;
var m,t:longint;
begin
if (x<=l) and (y>=r) then exit(tree[i].max)
else begin
m:=(l+r) shr ;
t:=-inf;
if x<=m then t:=max(t,getmax(i*,l,m,x,y));
if y>m then t:=max(t,getmax(i*+,m+,r,x,y));
exit(t);
end;
end; function getsum(i,l,r,x,y:longint):longint;
var m,t:longint;
begin
if (x<=l) and (y>=r) then exit(tree[i].sum)
else begin
m:=(l+r) shr ;
t:=;
if x<=m then t:=t+getsum(i*,l,m,x,y);
if y>m then t:=t+getsum(i*+,m+,r,x,y);
exit(t);
end;
end; function asksum(x,y:longint):longint;
var f1,f2:longint;
begin
asksum:=;
f1:=top[x];
f2:=top[y];
while f1<>f2 do
begin
if d[f1]>=d[f2] then
begin
asksum:=asksum+getsum(,,n,c[f1],c[x]);
x:=fa[f1];
end
else begin
asksum:=asksum+getsum(,,n,c[f2],c[y]);
y:=fa[f2];
end;
f1:=top[x];
f2:=top[y];
end;
if c[x]>c[y] then swap(x,y);
asksum:=asksum+getsum(,,n,c[x],c[y]);
end; function askmax(x,y:longint):longint;
var f1,f2,t:longint;
begin
t:=-inf;
f1:=top[x];
f2:=top[y];
while f1<>f2 do //提取
begin
if d[f1]>=d[f2] then
begin
t:=max(t,getmax(,,n,c[f1],c[x]));
x:=fa[f1];
end
else begin
t:=max(t,getmax(,,n,c[f2],c[y]));
y:=fa[f2];
end;
f1:=top[x];
f2:=top[y];
end;
if c[x]>c[y] then swap(x,y);
t:=max(t,getmax(,,n,c[x],c[y]));
exit(t);
end; begin
readln(n);
for i:= to n- do
begin
readln(x,y);
add(x,y);
add(y,x);
end;
d[]:=;
dfs1();
t:=;
top[]:=;
dfs2();
for i:= to n do
read(b[c[i]]);
build(,,n);
readln(m);
for i:= to m do
begin
read(ch);
s:='';
while ch<>' ' do
begin
s:=s+ch;
read(ch);
end;
readln(x,y);
if s='QMAX' then
writeln(askmax(x,y))
else if s='QSUM' then
writeln(asksum(x,y))
else if s='CHANGE' then
begin
x:=c[x];
b[x]:=y;
add(,,n);
end;
end;
end.

bzoj1036的更多相关文章

  1. 【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分

    [BZOJ1036][ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. ...

  2. 【bzoj1036】 ZJOI2008—树的统计Count

    http://www.lydsy.com/JudgeOnline/problem.php?id=1036 (题目链接) 题意 动态维护树上两点间最大权值和权值和. Solution 裸树链剖分. 这一 ...

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

    Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. Q ...

  4. BZOJ1036 [ZJOI2008]树的统计Count 树链剖分

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1036 题意概括 一个树,每个节点有一个权值.3种操作. 1:修改某一个节点的权值. 2:询问某两个 ...

  5. 【lct】bzoj1036 [ZJOI2008]树的统计Count

    题意:给你一棵树,点带权,支持三种操作:单点修改:询问链上和:询问链上max. 这里的Query操作用了与上一题不太一样的做法(上一题用那种做法,因为在边带权的情况下换根太困难啦): 先ChangeR ...

  6. [BZOJ1036][ZJOI2008]树的统计Count 解题报告|树链剖分

    树链剖分 简单来说就是数据结构在树上的应用.常用的为线段树splay等.(可现在splay还不会敲囧) 重链剖分: 将树上的边分成轻链和重链. 重边为每个节点到它子树最大的儿子的边,其余为轻边. 设( ...

  7. 洛谷3384&bzoj1036树链剖分

    值得注意的是: 一个点的子树是存在一起的...也就是说我们修改子树的时候只用... /********************************************************* ...

  8. 【BZOJ1036】树的统计Count(树链剖分,LCT)

    题意:一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: ...

  9. bzoj1036 [ZJOI2008]树的统计Count

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 12646  Solved: 5085 [Subm ...

  10. 【bzoj1036】[ZJOI2008]树的统计Count

    题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v ...

随机推荐

  1. shell入门之函数应用 分类: 学习笔记 linux ubuntu 2015-07-10 21:48 77人阅读 评论(0) 收藏

    最近在学习shell编程,文中若有错误的地方还望各位批评指正. 先来看一个简单的求和函数 #!/bin/bash #a test about function f_sum 7 8 function f ...

  2. Java基础知识强化之集合框架笔记23:ArrayList的实现原理

    1. ArrayList的实现原理: 这个可以直接参考网友的博客:http://www.cnblogs.com/ITtangtang/p/3948555.html

  3. Mysql表复制及备份还原

    1.复制表结构   1.1 含有主键等信息的完整表结构   CREATE table 新表名 LIKE book;     1.2 只有表结构,没有主键等信息   create table 新表名 s ...

  4. 基于Android_volley的Get、Post的方法

    用Android_volley加载网络信息有Get,post两种方式,通过一个例子来说明,在Activity中设置两个Button,分别测试Get.post方法 一般分为三步, 1. 创建一个Requ ...

  5. Android开发手记(28) Handler和Looper

    Android的消息处理有三个核心类:Looper,Handler和Message.其实还有一个Message Queue(消息队列),但是MQ被封装到Looper里面了,我们不会直接与MQ打交道.平 ...

  6. JVM Run-Time Data Areas.

    Ref: JVM Run-Time Data Areas class SimpleThread extends Thread { public SimpleThread(String name) { ...

  7. ORACLE多表关联UPDATE 语句

    转载至:http://blog.itpub.net/29378313/viewspace-1064069/ 为了方便起见,建立了以下简单模型,和构造了部分测试数据:在某个业务受理子系统BSS中, SQ ...

  8. 通常我们使用[NSDate date]方法得到的时间与当前时间不一致,如何解决?

    NSDate *date = [NSDate date];    NSTimeZone *zone = [NSTimeZone systemTimeZone];    NSInteger interv ...

  9. 【转载】C++应用引用计数技术

    原帖:http://www.cnblogs.com/chain2012/archive/2010/11/12/1875578.html 因为Windows的内核对象也运用了引用计数,所以稍作了解并非无 ...

  10. OC文件操作(1)

    1.文件的浅度遍历与深度遍历: //NSFileManager * fm = [[NSFileManager alloc]init];//创建文件管理器 //第一步创建一个文件管理器 NSError ...