松鼠的新家(lca)
洛谷—— P3258 [JLOI2014]松鼠的新家
题目描述
松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在”树“上。
松鼠想邀请小熊维尼前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去a1,再去a2,......,最后到an,去参观新家。可是这样会导致维尼重复走很多房间,懒惰的维尼不听地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。
维尼是个馋家伙,立马就答应了。现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。
因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。
输入输出格式
输入格式:
第一行一个整数n,表示房间个数第二行n个整数,依次描述a1-an接下来n-1行,每行两个整数x,y,表示标号x和y的两个房间之间有树枝相连。
输出格式:
一共n行,第i行输出标号为i的房间至少需要放多少个糖果,才能让维尼有糖果吃。
输入输出样例
5 1 4 5 3 2 1 2 2 4 2 3 4 5
1 2 1 2 1
说明
2<= n <=300000
思路:
对于这个题有些大佬肯定看一眼就能知道这个题是用的lca+插分做的吧。
(但像我这种蒟蒻是肯定不能一眼就看出来的!)
那有些人就要问啦,插分是个什么鬼?!
好,那我们先来说说插分吧!
随便写一个序列 3 6 2 7 5
它的查分序列是用后一个数减去前一个数,第一个数什么都不减就是它本身。
差分序列 3 3 -4 5 -2
差分序列有一个性质,就是你从头往后累加,加到第几个位置,现在累加的数就是原序列这个位置的数。
例如:差分序列加到第三个位置 3+3+(-4)=2;正好是原序列第三个位置的数。
应用一下吧。。。。我们要对一个区间的子区间进行操作.
例如[1,10];我们要将[4,6]这个区间的所有数加+1,求[4,6]的区间和。当然可以for循环挨个加1,求和;
那么差分是怎样求呢。我们只需更改两个位置,假如我们进行修改的区间是[l,r]。将a[l]+1,a[r+1]-1;即可完成区间的更改。
上面的例子 [4,6] .a[4]+1,a[6+1]-1;这样从头开始累加,由于我们在a[4]+1,我们从头累加到a[4-6]都会加+1;当我们累加到[4,6]
这个区间以外,由于a[6+1]已经-1,所以之后的累加都-1,都是它原来数的大小。为什么累加就是利用的差分序列的性质
来,我们来看看树上差分的结论:
1、将每条路径(s,t)上的每个点权值增加1,求各点权值。
将s、t点的权值加+1,lca(s,t)的权值-1,s和t的lca的爸爸-1。从叶子结点开始向上累加权值。
恍然大悟WAW。这道题真是赤裸裸的一道裸题啊。至于为什么那个点+那个点-,结合差分序列的性质自己顿悟。
2、找出被所有路径都覆盖的边
s,t的权值+1,s和t的lca的权值-2,从叶结点向上累加。
最终权值为路径数的点到其父亲的边为所求边。
所以我们把这个题访问的路径看成一个区间,区间的结点的权值都+1,就用差分做好了。
但是有一个坑,这一条路径的起点是这一条路径的终点,所以不能重复给糖,最后2--n减去1就可以。
好吧,废话少说,我们来直接看这道题的代码吧!
代码:
#include<vector>
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 300000+15
using namespace std;
vector<int>vec[N];
int fa[N],deep[N],n,m,top[N],ans,size[N],x,y,f[N],a[N],z;
int read(){
,f=;
char ch=getchar();
')
{
;
ch=getchar();
}
')
{
x=x*+ch-';
ch=getchar();
}
return x*f;
}
int lca(int x,int y)
{
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])
swap(x,y);
x=fa[top[x]];
}
if(deep[x]>deep[y])
swap(x,y);
return x;
}
void dfs(int x)
{
size[x]=;
deep[x]=deep[fa[x]]+;
;i<vec[x].size();i++)
if(vec[x][i]!=fa[x])
{
fa[vec[x][i]]=x;
dfs(vec[x][i]);
size[x]+=size[vec[x][i]];
}
}
void dfs1(int x)
{
;
if(!top[x]) top[x]=x;
;i<vec[x].size();i++)
if(vec[x][i]!=fa[x]&&size[vec[x][i]]>size[t])
t=vec[x][i];
if(t) top[t]=top[x],dfs1(t);
;i<vec[x].size();i++)
if(vec[x][i]!=fa[x]&&t!=vec[x][i])
dfs1(vec[x][i]);
}
void dfs2(int x)
{
;i<vec[x].size();i++)
if(fa[x]!=vec[x][i])
dfs2(vec[x][i]),f[x]+=f[vec[x][i]];
}
int main()
{
n=read();
;i<=n;i++)
a[i]=read();
;i<n;i++)
{
x=read(),y=read();
vec[x].push_back(y);
vec[y].push_back(x);
}
deep[]=;
dfs();
dfs1();
;i<=n;i++)
{
x=a[i-];
y=a[i];z=lca(x,y);
f[x]++;f[fa[y]]++;
f[z]--;f[fa[z]]--;
}
dfs2();
;i<=n;i++)
printf("%d\n",f[i]);
;
}
松鼠的新家(lca)的更多相关文章
- [JLOI2014] 松鼠的新家 (lca/树上差分)
[JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在 ...
- 【bzoj3631】[JLOI2014]松鼠的新家 LCA+差分数组
题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在“树”上.松鼠想邀请小熊维尼前来 ...
- P3258[JLOI2014]松鼠的新家(LCA 树上差分)
P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...
- 【BZOJ-3631】松鼠的新家 树形DP?+ 倍增LCA + 打标记
3631: [JLOI2014]松鼠的新家 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1231 Solved: 620[Submit][Stat ...
- [填坑]树上差分 例题:[JLOI2014]松鼠的新家(LCA)
今天算是把LCA这个坑填上了一点点,又复习(其实是预习)了一下树上差分.其实普通的差分我还是会的,树上的嘛,也是懂原理的就是没怎么打过. 我们先来把树上差分能做到的看一下: 1.找所有路径公共覆盖的边 ...
- 【洛谷】【lca+树上差分】P3258 [JLOI2014]松鼠的新家
[题目描述:] 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n(2 ≤ n ≤ 300000)个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真 ...
- [BZOJ3631]:[JLOI2014]松鼠的新家(LCA+树上差分)
题目传送门 题目描述: 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在“树”上.松鼠想邀 ...
- BZOJ 3631: [JLOI2014]松鼠的新家 树上差分 + LCA
Description 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在“树”上.松鼠想邀 ...
- BZOJ 3631 【JLOI2014】 松鼠的新家
Description 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在"树&q ...
随机推荐
- 谷歌放弃“不作恶” Alphabet要“遵守法律互相尊重”
对于一些谷歌粉而言,谷歌那条“不作恶(Don’t be evil)”的行为准则是他们引以为傲的精神信仰.这一准则于1999年被首次确认,谷歌在2004年申请上市时也提到了这一点.不过现在这一点要改变了 ...
- 我的Python分析成长之路6
模块:本质就是.py结尾的文件.从逻辑上组织python代码. 包: 本质就是一个目录,带有__init__.py文件,从逻辑上组织模块. 模块的分类: 1.标准库(内置的模块) 2.开源库(第三方库 ...
- UVALive - 8273 Assigning Frequencies (搜索 )
n个点的一张图,问能否给每个点染上三种颜色中的一种,使得没有相邻的点颜色相同? n <= 35. Sample Input 4 6 6 0 3 1 5 3 2 2 5 0 4 1 0 7 12 ...
- 加密javascript代码
最近看了个js日历,里面用到了加密,看了下,自己也模仿做加密,现在只能加密一般的javascript语句 <!DOCTYPE html> <html> <meta htt ...
- ThreeJs 基础入门
本文来自网易云社区 作者:唐钊 Three.js 是一款运行在浏览器中的 3D 引擎,你可以用它在 web 中创建各种三维场景,包括了摄影机.光影.材质等各种对象.使用它可以让我们更加直观的了解 we ...
- python-安装及配置环境变量
1.python安装十分简单,直接下载与自己电脑位数匹配的python安装包进行安装即可. 这里提供python27的安装包供大家参考. win-32位: 链接: https://pan.baidu. ...
- Emacs 安装与体验
Emacs 安装与体验 下载与安装 首先是下载最新的x64版本的Emacs. 将下载下来的文件解压到你喜欢的磁盘目录下,我选择的是C:\Program Files.放在D盘可能是更好的选择,因 ...
- JavaScript 专题系列第六篇,讲解深浅拷贝的技巧和以及实现深浅拷贝的思路
拷贝也是面试经典呐! 数组的浅拷贝 如果是数组,我们可以利用数组的一些方法比如:slice.concat 返回一个新数组的特性来实现拷贝. 比如: var arr = ['old', 1, tru ...
- [python学习篇] [os模块] [2]删除文件夹
def deleteDirectory(self,current_path): if not os.path.exists(current_path): self.logger.info(curren ...
- 【Luogu】P2219修筑绿化带(单调队列)
题目链接 这题各种边界判断恶心死人 就是单调队列在每行求出最小的.能装进A*B方块里的花坛 然后再在刚刚求出的那个东西里面跑一遍竖着的单调队列 然后……边界调了一小时 做完这题我深刻地感觉到我又强了 ...