题目描述
松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在”树“上。
松鼠想邀请小熊维尼前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去a1,再去a2,......,最后到an,去参观新家。可是这样会导致维尼重复走很多房间,懒惰的维尼不停地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。
维尼是个馋家伙,立马就答应了。现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。
因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。
输入输出格式
输入格式:
第一行一个整数n,表示房间个数第二行n个整数,依次描述a1-an
接下来n-1行,每行两个整数x,y,表示标号x和y的两个房间之间有树枝相连。
输出格式:
一共n行,第i行输出标号为i的房间至少需要放多少个糖果,才能让维尼有糖果吃。
一次AC很开心.
这个使用了树上差分算法的点差分.
但是呢, 我们要注意的是, 从第二个房间将要向后访问下一个房间的时候, 当前的房间是不需要在放糖果的, 我笔算了下, 在最后的bfs完后依次减一就行了.
开始我怕dfs会爆栈, 想先拓扑排序, 在bfs, 又闲麻烦, 就直接dfs了, 所幸没爆.
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
const int MAXN = 3e5 + 600;
const int MAXB = 22;
using namespace std;
int n, vis[MAXN];
int ihead[MAXN], ecnt;
int deep[MAXN];
struct Edge{
int to, next;
} edges[MAXN << 1 | 1];
int ancestor[MAXN][MAXB];
int diff[MAXN];
void init(){
memset(deep, -1, sizeof(deep));
memset(ihead, 0, sizeof(ihead));
ecnt = 0;
memset(ancestor, 0, sizeof(ancestor));
}
void insert(int u, int v){
Edge & e = edges[++ecnt];
e.to = v;
e.next = ihead[u];
ihead[u] = ecnt;
}
void bfs(){
queue<int> q;
q.push(1);
deep[1] = 0;
int u, v;
while(q.size()){
u = q.front();
q.pop();
for(int i = ihead[u]; i; i = edges[i].next){
Edge & e = edges[i];
if(deep[e.to] != -1){
continue;
}
q.push(e.to);
deep[e.to] = deep[u] + 1;
ancestor[e.to][0] = u;
}
}
for(int level = 1; level < MAXB; ++level){
for(int i = 1; i <= n; ++i){
ancestor[i][level] = ancestor[ancestor[i][level - 1]][level - 1];
}
}
}
int lca(int x, int y){
if(deep[x] < deep[y]){
swap(x, y);
}
for(int i = MAXB - 1; i > - 1; --i){
if(deep[ancestor[x][i]] >= deep[y]){
x = ancestor[x][i];
}
}
if(x == y){
return x;
}
for(int i = MAXB - 1; i > -1; --i){
if(ancestor[x][i] != ancestor[y][i]){
x = ancestor[x][i];
y = ancestor[y][i];
}
}
return ancestor[x][0];
}
void dfs(int u){
for(int i = ihead[u]; i; i = edges[i].next){
Edge & e = edges[i];
if(e.to != ancestor[u][0]){
dfs(e.to);
diff[u] += diff[e.to];
}
}
}
int main(){
init();
scanf("%d", &n);
for(int i = 0; i < n; ++i){
scanf("%d", vis + i);
}
int u, v;
for(int i = 1; i < n; ++i){
scanf("%d%d", &u, &v);
insert(u, v);
insert(v, u);
}
bfs();
for(int i = 1; i < n; ++i){
int s = vis[i - 1], d = vis[i];
int a = lca(s, d);
++diff[s];
++diff[d];
--diff[a];
--diff[ancestor[a][0]];
}
dfs(1);
for(int i = 1; i < n; ++i){
--diff[vis[i]];
}
for(int i = 0; i < n;){
printf("%d\n", diff[++i]);
}
return 0;
}