树链剖分 - 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 条双向航道,每条航道建立在两个星球之 ...
随机推荐
- 负载均衡 IO etc.
IO多路复用之epoll总结 ↑2013年8月21日11:49:44 EPOLL下的accept(不错的blog) 关于TCP封包.粘包.半包 linux内核TCP相关参数解释 ↑2013年8月14日 ...
- delphi 单引号在字符串中使用方法
可以看delph的帮助,里面有这个问题详细说明:A character string, also called a string literal or string constant, consist ...
- jQuery 插件开发解析
那么首先我们来简单的看一下最正统的 jQuery 插件定义方式: (function ($) { $.fn.插件名 = function (settings) { //默认参数 var default ...
- 使用WIF实现单点登录Part I——Windows Identity Foundation介绍及环境搭建
首先先说一下什么是WIF(Windows Identity Foundation).由于各种历史原因,身份验证和标识的管理一般都比较无规律可循.在软件里加入“身份验证”功能意味着要在你的代码里混进处理 ...
- python2.7抓取豆瓣电影top250
利用python2.7抓取豆瓣电影top250 1.任务说明 抓取top100电影名称 依次打印输出 2.网页解析 要进行网络爬虫,利用工具(如浏览器)查看网页HTML文件的相关内容是很有必要,我使用 ...
- python使用简单http协议来传送文件
python使用简单http协议来传送文件!在ubuntu环境下,局域网内可以使用nc来传送文件,也可以使用基于Http协议的方式来下载文件我们可以使用python -m SimpleHTTPServ ...
- rails的字符编码
想练练手,随意的写了个登陆页面,简单的只有几行. <%= form_tag('login_check') do -%><%= text_field_tag 'user_name', ...
- hihoCoder-1000-A+B
题目描述:传统的A+B题 使用语言:C 代码: #include <stdio.h> int main(void){ int a,b; while((scanf("%d %d&q ...
- Windows上搭建android开发环境
在搭建android开发环境时需要四部分内容,框架如下 其中Java SDK和Eclipse在java4android中有过介绍,重点介绍ADT和Android SDK的安装. 安装Android S ...
- 刀哥多线程全局队列gcd-09-global_queue
全局队列 是系统为了方便程序员开发提供的,其工作表现与并发队列一致 全局队列 & 并发队列的区别 全局队列 没有名称 无论 MRC & ARC 都不需要考虑释放 日常开发中,建议使用& ...