【题目描述:】

松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n(2 ≤ n ≤ 300000)个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在”树“上。

松鼠想邀请小熊维尼前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去a1,再去a2,......,最后到an,去参观新家。可是这样会导致维尼重复走很多房间,懒惰的维尼不停地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。

维尼是个馋家伙,立马就答应了。现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。

因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。

【输入格式:】

第一行一个整数n,表示房间个数第二行n个整数,依次描述a1-an

接下来n-1行,每行两个整数x,y,表示标号x和y的两个房间之间有树枝相连。

【输出格式:】

一共n行,第i行输出标号为i的房间至少需要放多少个糖果,才能让维尼有糖果吃。

输入样例#: 

输出样例#: 

输入输出样例

【算法分析:】

根据小熊维尼走的路径记录每个点走过的次数,就是需要放的糖果数目

从点i走到点j, 可以看做:从i走到lca(i, j)再走到j是最短的路径。

而如何把i -> lca, j -> lca的点全部自增1呢?

可以用树上差分来维护,设定一个一维数组cha

对于从i到j的一条路径,

cha[i]++; cha[j]++;
cha[lca(i, j)]--;
cha[f[lca(i, j)][]]--;//点i, j最近公共祖先的父节点

然后从根节点开始dfs这棵树,对cha数组做一遍前缀和

最后对所有既是起点也是重点的点的经过次数-1.

【代码:】

 //P3258 [JLOI2014]松鼠的新家
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std; const int MAXN = + ;
const int K = + ; int n, a[MAXN], ans[MAXN];
int cha[MAXN];
int deep[MAXN], f[MAXN][K];
int edge_num, head[MAXN];
struct Edge {
int to, next;
}h[MAXN << ]; inline int read() {
int x = , f = ; char ch = getchar();
while(ch < '' || ch > '') {
if(ch == '-') f = -;
ch = getchar();
}
while(ch >= '' && ch <= '')
x = (x << ) + (x << ) + ch - , ch = getchar();
return x * f;
} inline void Add(int from, int to) {
h[++edge_num].to = to;
h[edge_num].next = head[from];
head[from] = edge_num;
} void build(int u) {
for(int i = head[u]; i != -; i = h[i].next) {
if(!deep[h[i].to]) {
deep[h[i].to] = deep[u] + ;
f[h[i].to][] = u;
build(h[i].to);
}
}
} inline void fill() {
for(int j = ; j < K; ++j)
for(int i = ; i <= n; ++i)
f[i][j] = f[f[i][j - ]][j - ];
} int lca(int a, int b) {
if(deep[a] > deep[b])
swap(a, b);
for(int i = K - ; i >= ; --i)
if(deep[f[b][i]] >= deep[a]) b = f[b][i];
if(a == b) return a;
for(int i = K - ; i >= ; --i) {
if(f[b][i] != f[a][i]) {
a = f[a][i], b = f[b][i];
}
}
return f[b][];
} void dfs(int u) {
for(int i = head[u]; i != -; i = h[i].next) {
if(h[i].to == f[u][]) continue;
dfs(h[i].to);
cha[u] += cha[h[i].to];
}
} int main() {
memset(head, -, sizeof(head));
n = read();
for(int i = ; i <= n; ++i) a[i] = read();
for(int i = ; i < n; ++i) {
int x = read(), y = read();
Add(x, y);
Add(y, x);
}
deep[a[n]] = ;
build(a[n]);
fill();
for(int i = ; i <= n; ++i) {
int com = lca(a[i], a[i - ]);
++cha[a[i]], ++cha[a[i - ]];
--cha[com], --cha[f[com][]];
}
dfs(a[n]);
for(int i = ; i <= n; ++i)
--cha[a[i]];
for(int i = ; i <= n; ++i)
printf("%d\n", cha[i]);
}

【洛谷】【lca+树上差分】P3258 [JLOI2014]松鼠的新家的更多相关文章

  1. P3258[JLOI2014]松鼠的新家(LCA 树上差分)

    P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...

  2. 洛谷 P3258 [JLOI2014]松鼠的新家 树链剖分+差分前缀和优化

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 说明 思路 AC代码 优化 优化后AC代码 总结 题面 题目链接 P3258 [JLOI2 ...

  3. 洛谷 P3258 [JLOI2014]松鼠的新家 题解

    P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...

  4. 洛谷 P3258 [JLOI2014]松鼠的新家 解题报告

    P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...

  5. 洛谷P3258 [JLOI2014]松鼠的新家

    P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...

  6. P3258 [JLOI2014]松鼠的新家

    P3258 [JLOI2014]松鼠的新家倍增lca+树上差分,从叶子节点向根节点求前缀和,dfs求子树和即可,最后,把每次的起点和终点都. #include<iostream> #inc ...

  7. 洛谷P3258 [JLOI2014]松鼠的新家(树上差分+树剖)

    题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在”树“上. 松鼠想邀请小熊维尼前 ...

  8. 洛谷——P3258 [JLOI2014]松鼠的新家

    https://www.luogu.org/problem/show?pid=3258 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到 ...

  9. 洛谷 P3258 [JLOI2014]松鼠的新家(树链剖分)

    题目描述松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在”树“上. 松鼠想邀请小熊维尼前来 ...

随机推荐

  1. .net core 2.2 部署CentOS7(2)给虚拟机安装CentOS7

    目录: .net core 2.2 部署CentOS7(1)安装虚拟机 .net core 2.2 部署CentOS7(2)给虚拟机安装CentOS7 .net core 2.2 部署CentOS7( ...

  2. [日常] MySQL的哈希索引和原理研究测试

    1.哈希索引 :(hash index)基于哈希表实现,只有精确匹配到索引列的查询,才会起到效果.对于每一行数据,存储引擎都会对所有的索引列计算出一个哈希码(hash code),哈希码是一个较小的整 ...

  3. [javaEE] http协议详细

    上一篇:http://www.cnblogs.com/taoshihan/p/5346731.html HTTP请求 请求行 GET /taoshihan/p/5346731.html HTTP/1. ...

  4. [AMPPZ2014]Petrol

    关键点的最小生成树? 关键点初始化为0,跑多源最短路,然后重构整个图,用Kruskal跑最小生成树 然后跑树链剖分在线回答询问 对树上每个点维护到链顶的最大值,结合线段树可以做到\(\Theta(n ...

  5. python条件判断和循环

    条件判断 if <条件判断1>: <执行1> elif <条件判断2>: <执行2> elif <条件判断3>: <执行3> e ...

  6. C# Visual 快捷键

      编辑系 代码提示 Ctrl + J激活VS默认代码提示功能.ReSharper等插件会建议你修改快捷键. 导入命名空间 个人认为Ctrl + .是最方便的,复杂点的是Alt + Shift + F ...

  7. TensorFlow分布式部署【多机多卡】

    让TensorFlow们飞一会儿 前一篇文章说过了TensorFlow单机多卡情况下的分布式部署,毕竟,一台机器势单力薄,想叫兄弟们一起来算神经网络怎么办?我们这次来介绍一下多机多卡的分布式部署. 其 ...

  8. Flutter隐藏控件方法

    new Offstage( offstage: true, //这里控制 child: Container(color: Colors.blue,height: 100.0,), ),

  9. 一步一步pwn路由器之radare2使用实战

    前言 本文由 本人 首发于 先知安全技术社区: https://xianzhi.aliyun.com/forum/user/5274 前文讲了一些 radare2 的特性相关的操作方法.本文以一个 c ...

  10. Claims-based认证解析

    Claims-based认证相关的两个重要的类ClaimsIdentity以及ClaimsPrincipal解析 ClaimsIdentity以及ClaimsPrincipal是.NET下Claims ...