【题目描述:】

松鼠的新家是一棵树,前几天刚刚装修了新家,新家有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. Java springmvc 统一异常处理的方案

    前言:为什么要统一异常处理?经常在项目中需要统一处理异常,将异常封装转给前端.也有时需要在项目中统一处理异常后,记录异常日志,做一下统一处理. Springmvc 异常统一处理的方式有三种. 一.使用 ...

  2. python之多进程multiprocessing模块

    process类介绍 multiprocessing 模块官方说明文档 Process 类用来描述一个进程对象.创建子进程的时候,只需要传入一个执行函数和函数的参数即可完成 Process 示例的创建 ...

  3. QT的信号和槽机制简介

    信号与槽作为QT的核心机制在QT编程中有着广泛的应用,本文介绍了信号与槽的一些基本概念.元对象工具以及在实际使用过程中应注意的一些问题. QT是一个跨平台的C++ GUI应用构架,它提供了丰富的窗口部 ...

  4. Ubuntu16.04安装jupiter

    Ubuntu16.04安装jupiter 1.安装pip pip是一个安装和管理 Python 包的工具, 是 easy_install 的一个替换品.自然对应Python3,则有pip3. Pyth ...

  5. webpack2引入bootstrap的坑

    在webpack官网教程的代码分离-css章节中,给出的例子是这样的. //安装 ExtractTextWebpackPlugin 如下 npm install --save-dev extract- ...

  6. requireJS中如何用r.js对js进行合并和压缩css文件

    我运行的环境是windows+node.js,首先是用npm安装requirejs(全局安装,即使用 'npm install requirejs -g',这样方便在各个目录调用),接着就是下载r.j ...

  7. SLAM会被深度学习方法取代吗?

    日益感觉到自己对深度学习的理解比较肤浅,这段且当做是以前的认识. 上上周去围观了泡泡机器人和AR酱联合举办的论坛.在圆桌阶段,章国峰老师提了一个问题:SLAM会被深度学习方法取代吗?这是一个很有趣的话 ...

  8. 润乾报表与DERBY数据库的创建连接详解

     1. 问题概述 1.Derby数据库的创建过程 2.润乾报表连接Derby数据库展现数据 概述: Derby是Apache Software Foundation (ASF)的一个的孵化器项目. ...

  9. 2Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

    public class TestException { public static void main(String[] args) { String str = "1"; fo ...

  10. gearman入门初步

    原文地址:http://blog.sina.com.cn/s/blog_5f54f0be0101btsi.html     PHP 没有提供直接的并发功能.要实现并发,必须: function asy ...