树链剖分 - 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 条双向航道,每条航道建立在两个星球之 ...
随机推荐
- 16.python中的浅拷贝和深拷贝
在讲什么是深浅拷贝之前,我们先来看这样一个现象: a = ['scolia', 123, [], ] b = a[:] b[2].append(666) print a print b
- [terry笔记]Oracle10g/11g安装-redhat5.5
操作系统准备工作 其实真正的进入图形界面安装是简单的,只是前期的配置比较繁琐,如版本.空间.位置.软件包.用户.环境变量.内核参数,这里主要讨论前期配置. 10g与11g的单实例安装基本一样,主要区别 ...
- Android WebView代理设置方法(API10~21适用)
最近碰到个需求需要在APP中加入代理,HttpClient的代理好解决,但是WebView碰到些问题,然后找到个API10~API21都通用的类,需要用的同学自己看吧,使用方法,直接调用类方法setP ...
- linux中fork()函数详解
一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同, ...
- hdu 1509 Windows Message Queue
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1509 Windows Message Queue Description Message queue ...
- 开发移动app与服务器端session的状态管理与交互
我们进行web开发的时候,一般使用cookie或session来保存用户的登录状态,通过检查cookie或session的数据来验证用户是否具有对某些需要登录的页面的访问权限,这一切都是通过浏览器来完 ...
- 在WIN7下安装运行mongodb 1)、下载MongoDB
1).下载MongoDB http://downloads.mongodb.org/win32/mongodb-win32-i386-2.4.5.zip 下载Windows 32-bit版本并解压缩, ...
- Swift Tips - 当 Swift 遇上 CocoaPods
CocoaPods 作为 iOS 开发的包管理工具,几乎成为了 Objective-C 的行业标准.它为我们提供了非常方便的包管理功能.而苹果正式发布 Swift 语言也已经有半年多时间了,Swift ...
- perl DBI 学习总结(转载)
perl DBI 学习总结 源文地址:http://blog.csdn.net/like_zhz/article/details/5441946 DBI和DBD的不同关系模型: ########### ...
- 零基础学习Linux(三)linux与windows文件共享
上次的博文零基础学习Linux(一)环境搭建中我们已经将linux环境部署完毕了,接下来我们就可以在linux上进行软件的安装和环境的配置.但在进行这些操作之前,我们还需要解决一个问题——Linux与 ...