【题目描述:】

松鼠的新家是一棵树,前几天刚刚装修了新家,新家有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. fuzhou 1075 分解素因子

    Problem 1075 分解素因子 Accept: 1331    Submit: 2523Time Limit: 1000 mSec    Memory Limit : 32768 KB Prob ...

  2. drupal7 带表达式条件的update

    原本的mysql语句是这样的: ; 转化成drupal的api是这样的 $total_amount=1; $rows= db_update('my_payment_card') ->expres ...

  3. mybatis逆向文件

    一.mapper接口中的方法解析 mapper接口中的函数及方法 方法 功能说明 int countByExample(UserExample example) thorws SQLException ...

  4. Python的正则表达式与JSON

    Python的正则表达式需要导入re模块 菜鸟教程:http://www.runoob.com/python/python-reg-expressions.html 官方文档:https://docs ...

  5. ubuntu下使用g++编译时默认支持C++11 配置方法

    1.只需要在源文件程序中加上如下一行代码: #pragma GCC diagnostic error "-std=c++11" 此时源文件代码如下: #pragma GCC dia ...

  6. OpenGL学习--02--绘制一个红色三角形

    The OpenGL buffer is created, bound, filled and configured with the standard functions (glGenBuffers ...

  7. 封装一个 TopBarBaseActivity

    什么是快速开发嘞,看这个效果 然而我只用了这么几行代码: activity_main.xml 里面什么也没有! 其实说白了哈,就是我把 TopBar 封装在 TopBarBaseActivity 里面 ...

  8. Android Viewpager+Fragment实现滑动标签页

    ViewPager 结合Fragment实现一个Activity里包含多个可滑动的标签页,每个标签页可以有独立的布局及响应. 主页布局 <?xml version="1.0" ...

  9. org.springframework.data.redis.cache.RedisCacheManager

    org.springframework.data.redis.cache.RedisCacheManager

  10. UnicodeEncodeError: 'ascii' codec can't encode characters in position 2-5: ordin al not in range(128)——解决方案备注

    在vim中使用ycm插件时,偶尔会出现: “UnicodeEncodeError: 'ascii' codec can't encode characters in position 2-5: ord ...