这是树链剖分的入门题,也是我学树链剖分的第一题。

树链剖分:就是把树中和线段树联系起来,求(u,v)路径中权值的最大值和其路径的权值和。

入门blog:http://blog.sina.com.cn/s/blog_7a1746820100wp67.html

https://quartergeek.com/summary-of-heavy-light-decomposition/

kuangbin 菊苣的专题训练:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28982#overview

我的第一树链

#include<bits/stdc++.h>
using namespace std;
#define N 30010 struct Edge
{
int to,next;
}edge[N*]; int head[N],tot;
int top[N],fa[N],deep[N],num[N],p[N],fp[N],son[N],pos; void init()
{
tot=;
memset(head,-,sizeof(head));
pos=;
memset(son,-,sizeof(son));
} void addedge(int u,int v)
{
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot++;
} void dfs1(int u,int pre,int d)
{
deep[u]=d;
fa[u]=pre;
num[u]=;
for (int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].to;
if (v!=pre)
{
dfs1(v,u,d+);
num[u]+=num[v];
if (son[u]==-||num[v]>num[son[u]])
son[u]=v;
}
}
} void getpos(int u,int sp)
{
top[u]=sp;
p[u]=pos++;
fp[p[u]]=u;
if (son[u]==-) return;
getpos(son[u],sp);
for (int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].to;
if (v!=son[u]&&v!=fa[u]) getpos(v,v);
}
}
struct node
{
int l,r;
int sum;
int Max;
}tree[N*];
void push_up(int i)
{
tree[i].sum=tree[i<<].sum+tree[i<<|].sum;
tree[i].Max=max(tree[i<<].Max,tree[i<<|].Max);
}
int s[N]; void build(int i,int l,int r)
{
tree[i].l=l;
tree[i].r=r;
if (l==r)
{
tree[i].sum=tree[i].Max=s[fp[l]];
return;
} int mid=(l+r)>>;
build(i<<,l,mid);
build(i<<|,mid+,r);
push_up(i);
}
void update(int i,int k,int val)
{
if (tree[i].l==k&&tree[i].r==k)
{
tree[i].sum=tree[i].Max=val;
return;
}
int mid=(tree[i].l+tree[i].r)/;
if (k<=mid) update(i<<,k,val);
else update(i<<|,k,val);
push_up(i);
} int query_max(int i,int l,int r)
{
if (tree[i].l==l&&tree[i].r==r)
return tree[i].Max;
int mid=(tree[i].l+tree[i].r)/;
if (r<=mid) return query_max(i<<,l,r);
else if (l>mid) return query_max(i<<|,l,r);
else return max(query_max(i<<,l,mid),query_max(i<<|,mid+,r));
} int query_sum(int i,int l,int r)
{
if (tree[i].l==l&&tree[i].r==r)
return tree[i].sum;
int mid=(tree[i].l+tree[i].r)/;
if (r<=mid) return query_sum(i<<,l,r);
else if (l>mid) return query_sum(i<<|,l,r);
else return query_sum(i<<,l,mid)+query_sum(i<<|,mid+,r);
} int findmax(int u,int v)
{
int f1=top[u],f2=top[v]; int tmp=-;
while (f1!=f2)
{
if (deep[f1]<deep[f2])
{
swap(f1,f2);
swap(u,v);
}
tmp=max(tmp,query_max(,p[f1],p[u]));
u=fa[f1];
f1=top[u];
}
if (deep[u]>deep[v]) swap(u,v);
return max(tmp,query_max(,p[u],p[v]));
} int findsum(int u,int v)
{
int f1=top[u],f2=top[v];
int tmp=;
while (f1!=f2)
{
if (deep[f1]<deep[f2])
{
swap(f1,f2);
swap(u,v);
}
tmp+=query_sum(,p[f1],p[u]);
u=fa[f1];
f1=top[u];
}
if (deep[u]>deep[v]) swap(u,v);
return tmp+query_sum(,p[u],p[v]);
} int main()
{
int n;
int q;
char op[];
int u,v;
while(scanf("%d",&n) == )
{
init();
for(int i = ;i < n;i++)
{
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
for(int i = ;i <= n;i++)
scanf("%d",&s[i]);
dfs1(,,);
getpos(,);
build(,,pos-);
scanf("%d",&q);
while(q--)
{
scanf("%s%d%d",op,&u,&v);
if(op[] == 'C')
update(,p[u],v);//修改单点的值
else if(strcmp(op,"QMAX") == )
printf("%d\n",findmax(u,v));//查询u->v路径上点权的最大值
else printf("%d\n",findsum(u,v));//查询路径上点权的和
}
}
return ;
}

份代码:

树链剖分 - BZOJ 1036: [ZJOI2008]树的统计Count的更多相关文章

  1. 数据结构(LCT动态树):BZOJ 1036: [ZJOI2008]树的统计Count

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 12266  Solved: 4945[Submit ...

  2. 【块状树】【树链剖分】bzoj1036 [ZJOI2008]树的统计Count

    很早之前用树链剖分写过,但是代码太长太难写,省选现场就写错了. #include<cstdio> #include<algorithm> #include<cstring ...

  3. BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)

    BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...

  4. bzoj 1036: [ZJOI2008]树的统计Count——树链剖分

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

  5. BZOJ 1036: [ZJOI2008]树的统计Count 【树链剖分】

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

  6. BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

  7. BZOJ 2243:染色(树链剖分+区间合并线段树)

    [SDOI2011]染色Description给定一棵有n个节点的无根树和m个操作,操作有2类:1.将节点a到节点b路径上所有点都染成颜色c:2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认 ...

  8. BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector

    题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...

  9. Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分)

    Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分) Description L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之 ...

随机推荐

  1. 6)Java中String类

    1)String对象的初始化   由于String对象特别常用,所以在对String对象进行初始化时,Java提供了一种简化的特殊语法,格式如下:     String s = “abc”;     ...

  2. cursorfilter

    android.widget.CursorAdapter它首先实现了两个接口Filterable,CursorFilter.CursorFilterClient.其中Filterable接口定义了ge ...

  3. MySQL线上执行大事务或锁表操作

    前提 在线执行一些大事务或锁表操作(给某个核心级表加一列或者执行修改操作),此时不但主库从库要长时间锁表,主从延迟也会变大.未避免大事务sql对整个集群产生影响,,我们希望一条SQL语句只在Maste ...

  4. 【转】 BSS段 数据段 代码段 堆栈 指针 vs 引用

    原文:http://blog.csdn.net/godspirits/article/details/2953721 BSS段 数据段 代码段 堆栈 (转+) 声明:大部分来自于维基百科,自由的百科全 ...

  5. Python 有哪些优点?为何要学Python?

      1. 支持OOP编程 从根本上讲Python仍是一种面向对象的语言,支持多态.继承等高级概念,在Python里使用OOP十分容易 没有C++.Java那样复杂,但不必做Python下OOp高手,够 ...

  6. opengl基础学习专题 (二) 点直线和多边形

    题外话 随着学习的增长,越来越觉得自己很水.关于上一篇博文中推荐用一个 学习opengl的 基于VS2015的 simplec框架.存在 一些问题. 1.这个框架基于VS 的Debug 模式下,没有考 ...

  7. main函数的argc和argv

      int main(int argc, char const *argv[]) { printf("argc : %c\n",argc); printf(] ); printf( ...

  8. android 的生命周期自我理解

    android的active的生命周期,经过网站的blog学习,加上自己的理解总结如下: 第1种:全新的启动应用程序顺序 onCreate--->onStart---->onResume ...

  9. sql server 小记——分区表

    我们知道很多事情都存在一个分治的思想,同样的道理我们也可以用到数据表上,当一个表很大很大的时候,我们就会想到将表拆 分成很多小表,查询的时候就到各个小表去查,最后进行汇总返回给调用方来加速我们的查询速 ...

  10. R 语言中文乱码问题

    R 语言似乎在WINDOWS平台上对中文的支持不是特别好,似乎是3.1.2的一个BUG. 目前我研究出了一个临时解决方案,你可以将代码编写成一个函数,从而在调用的过程中不必如下繁琐: 1. 先将本地语 ...