[BZOJ] 3631: [JLOI2014]松鼠的新家

3631: [JLOI2014]松鼠的新家

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 2246  Solved: 1148
[Submit][Status][Discuss]

Description

松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在“树”上。松鼠想邀请小熊维尼前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去a1,再去a2,……,最后到an,去参观新家。
可是这样会导致维尼重复走很多房间,懒惰的维尼不听地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。维尼是个馋家伙,立马就答应了。
现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。

Input

第一行一个整数n,表示房间个数
第二行n个整数,依次描述a1-an
接下来n-1行,每行两个整数x,y,表示标号x和y的两个房间之间有树枝相连。

Output

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

Sample Input

5
1 4 5 3 2
1 2
2 4
2 3
4 5

Sample Output

1
2
1
2
1

HINT

 

2<= n <=300000

Source

Analysis

树上差分的例题 qwq

无非是树上的某一条路径点权集体+1s

那么树上差分解决

心情很差qwq不写教程了

需要注意的是,题目有一个要求:每次移动的终点权值-1s

Code

 1 #include<cstdio>
 2 #include<iostream>
 3 #define maxn 303030
 4 using namespace std;
 5 
 6 int depth[maxn],val[maxn],n,arr[maxn],fa[maxn][20];
 7 
 8 struct edge{
 9     int from,v;
10 }e[maxn*2];
11 int tot,first[maxn];
12 void insert(int u,int v){
13     tot++; e[tot].from = first[u]; e[tot].v = v;
14     first[u] = tot;
15 }
16 
17 void dfs(int now){
18     for(int i = first[now];i;i = e[i].from){
19         int v = e[i].v;
20         if(v != fa[now][0]){
21             depth[v] = depth[now]+1;
22             fa[v][0] = now;
23             dfs(v);
24         }
25     }
26 }
27 
28 void dfs2(int now){
29     for(int i = first[now];i;i = e[i].from){
30         int v = e[i].v;
31         if(v != fa[now][0]){
32             dfs2(v);
33             val[now] += val[v];
34         }
35     }
36 }
37 
38 void Init(){
39     for(int i = 1;i <= 18;i++)
40     for(int j = 1;j <= n;j++)
41         fa[j][i] = fa[fa[j][i-1]][i-1];
42 }
43 
44 int LCA(int u,int v){
45     if(depth[u] < depth[v]) swap(u,v);
46     for(int i = 18;i > -1;i--)
47         if(depth[fa[u][i]] >= depth[v])
48             u = fa[u][i];
49     if(u == v) return u;
50     for(int i = 18;i > -1;i--)
51         if(fa[u][i] != fa[v][i])
52             u = fa[u][i],v = fa[v][i];
53     return fa[u][0];
54 }
55 
56 int main(){
57     scanf("%d",&n);
58     
59     for(int i = 1;i <= n;i++)
60         scanf("%d",&arr[i]);
61     for(int i = 1;i < n;i++){
62         int x,y; scanf("%d%d",&x,&y);
63         insert(x,y); insert(y,x);
64     }depth[1] = 1; dfs(1);
65     Init();
66     
67     for(int i = 1;i < n;i++){
68         int anc = LCA(arr[i],arr[i+1]);
69         if(anc == arr[i]){
70             val[fa[anc][0]]--,val[arr[i+1]]++;
71         }else if(anc == arr[i+1]){
72             val[fa[anc][0]]--,val[arr[i]]++;
73         }else{
74             val[fa[anc][0]]--,val[anc]--;
75             val[arr[i]]++,val[arr[i+1]]++;
76         }val[fa[arr[i+1]][0]]++,val[arr[i+1]]--;
77 //        for(int i = 0;i <= n;i++) printf("%d ",val[i]);cout << endl;
78     }dfs2(1);
79     
80     for(int i = 1;i <= n;i++) printf("%d
",val[i]);
81     
82     return 0;
83 }
心情很差
原文地址:https://www.cnblogs.com/Chorolop/p/7632825.html