树链剖分 - BZOJ 1036: [ZJOI2008]树的统计Count
这是树链剖分的入门题,也是我学树链剖分的第一题。
树链剖分:就是把树中和线段树联系起来,求(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的更多相关文章
- 数据结构(LCT动态树):BZOJ 1036: [ZJOI2008]树的统计Count
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 12266 Solved: 4945[Submit ...
- 【块状树】【树链剖分】bzoj1036 [ZJOI2008]树的统计Count
很早之前用树链剖分写过,但是代码太长太难写,省选现场就写错了. #include<cstdio> #include<algorithm> #include<cstring ...
- BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)
BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...
- bzoj 1036: [ZJOI2008]树的统计Count——树链剖分
Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. Q ...
- BZOJ 1036: [ZJOI2008]树的统计Count 【树链剖分】
Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. Q ...
- BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...
- BZOJ 2243:染色(树链剖分+区间合并线段树)
[SDOI2011]染色Description给定一棵有n个节点的无根树和m个操作,操作有2类:1.将节点a到节点b路径上所有点都染成颜色c:2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认 ...
- BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector
题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...
- Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分)
Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分) Description L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之 ...
随机推荐
- win7修改软件【授权给…】后面的名称
很简单,按下图打开注册表,修改: Ctrl+F分别搜索以下三个键值,搜到后修改为你想显示的名称即可即可. 1:UserName 2:RegisteredOrganazition 3:Registere ...
- STM32F0xx_TIM基本延时配置详细过程
前言 关于定时器大家都应该不会陌生,因为处理器都有这个功能.今天总结的F0系列芯片的定时器根据芯片型号不同,数量也不同.定时器分类:基本定时器.通用定时器和高级定时器.计数位数也有不同,有16位的,有 ...
- Git - Tutorial [Lars Vogel]
From: http://www.vogella.com/tutorials/Git/article.html Git - Tutorial Lars Vogel Version 5.6 Copyri ...
- openSUSE13.1无法打开Yast的安装/移除软件管理软件的解决办法·(未解决,临时方法) 收获:有问题,读日志
看了日志发现错误在于Ruby,新的YaST是基于Ruby的,而我用rvm安了新版本Ruby,日志里这么出错: 2014-08-22 20:20:57 <3> linux-vfpp.site ...
- PF_RING 总结
1.背景 目前收包存在的问题: 第一:inpterrupt livelock, 当收到包的时候,网卡驱动程序就会产生一次中断.在大流量的情况下,操作系统将花费大量时间用于处理中断,而只有 少量的时间用 ...
- java中对象的序列化和反序列化
[对象的序列化和反序列化 ] 1.定义:序列化--将对象写到一个输出流中.反序列化则是从一个输入流中读取一个对象.类中的成员必须是可序列化的,而且要实现Serializable接口,这样的类的对象才能 ...
- AppCan认为,移动APP开发不是技术活
很多粉丝反应,AppCan的文章太专业了,技术大大们毫不费劲,小白看的晕乎乎. 时代变了,5年前,AppCan的受众只有开发者.现在,政府高管.集团董事长.非技术类管理者.中小企业主.各行各业的管理者 ...
- Android-简单的sdcard文件浏览
功能:能够浏览手机里面的文件夹和文件,代码灰常简单 先看布局 <LinearLayout xmlns:android="http://schemas.android.com/apk/r ...
- hdu 1880 魔咒词典
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1880 魔咒词典 Description 哈利波特在魔法学校的必修课之一就是学习魔咒.据说魔法世界有10 ...
- IBM X3650 M4安装win 2008 Server操作指南
由于IBM服务器是IBM原有的Linux系统,所以需要在此硬件上安装Win 2008 Server系统(以下简称win8),中间遇到了很多坑,在下面的描述中会阐述.以下是安装的整个步骤: 一.所需工具 ...