NC20139 [JLOI2014]松鼠的新家
题目
题目描述
松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在“树”上。
松鼠想邀请维尼小熊前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去a1,再去a2,……,最后到an,去参观新家。
可是这样会导致维尼重复走很多房间,懒惰的维尼不听地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。维尼是个馋家伙,立马就答应了。
现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。
因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。
输入描述
第一行一个整数n,表示房间个数
第二行n个整数,依次描述a1-an
接下来n-1行,每行两个整数x,y,表示标号x和y的两个房间之间有树枝相连。
输出描述
一共n行,第i行输出标号为i的房间至少需要放多少个糖果,才能让维尼有糖果吃。
示例1
输入
5
1 4 5 3 2
1 2
2 4
2 3
4 5
输出
1
2
1
2
1
备注
对于全部的数据,\(2 \le n \le 3 \times 10^5,1 \le a_i \le n\) 。
题解
知识点:差分,LCA。
可以用树剖解决,但对于这种最后查询的问题,可以不那么麻烦,用树上差分就行。
我们对相邻两个点的路径做路径加 \(1\) ,可以差分配合LCA实现,最后用做一次树上前缀和即可。
注意,两次路径的端点相交处只需要走一次,因此我们我们对相交的点的答案减 \(1\) 即可。
时间复杂度 \(O(n \log n)\)
空间复杂度 \(O(n \log n)\)
代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 3e5 + 7;
int a[N];
vector<int> g[N];
int f[27][N], dep[N];
void dfs(int u, int fa) {
f[0][u] = fa;
dep[u] = dep[fa] + 1;
for (int i = 1;i <= 20;i++) f[i][u] = f[i - 1][f[i - 1][u]];
for (auto v : g[u]) {
if (v == fa) continue;
dfs(v, u);
}
}
int LCA(int u, int v) {
if (dep[u] < dep[v]) swap(u, v);
for (int i = 20;i >= 0;i--) {
if (dep[f[i][u]] >= dep[v]) u = f[i][u];
if (u == v) return u;
}
for (int i = 20;i >= 0;i--) {
if (f[i][u] != f[i][v]) {
u = f[i][u];
v = f[i][v];
}
}
return f[0][u];
}
int dist(int u, int v) { return dep[u] + dep[v] - 2 * dep[LCA(u, v)]; }
int delta[N], add[N];
void calc(int u, int fa) {
for (auto v : g[u]) {
if (v == fa) continue;
calc(v, u);
delta[u] += delta[v];
}
}
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
for (int i = 1;i <= n;i++) cin >> a[i];
for (int i = 1;i <= n - 1;i++) {
int u, v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1, 0);
for (int i = 2;i <= n;i++) {
int u = a[i - 1], v = a[i];
int lca = LCA(u, v);
delta[u]++;
delta[v]++;
delta[lca]--;
delta[f[0][lca]]--;
}
calc(1, 0);
for (int i = 2;i <= n;i++) delta[a[i]]--;
for (int i = 1;i <= n;i++) cout << delta[i] << '\n';
return 0;
}
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/17499185.html