Replay


 

Dup4:

  • 厕所是个换换脑子的好地方?
  • 要读题啊,不要别人不做,自己就跟着不做啊

 X:

  • 读题很重要啊!什么时候才能读对题 不演队友啊 D题看错题, 直到最后一小时才看懂
  • 很多时候要看榜单做题

 

 

 

A:Aqours

Solved.

考虑一个点的子树下面有多少个叶子节点汇聚,

那么这个时候就可以更新某些叶子节点的答案

并且把距离该点最近的叶子节点返回上去继续做这一步操作

再正着  考虑除子树外 的离当前点最近的叶子节点的距离,用于更新子树中叶子结点的答案

相当于树形dp起手式

但是这里$n很大,不能DFS$

但是又注意到$i <= j  有 fa[i] < fa[j]$

相当于$bfs序列是1\;2\;\cdots n$

可以直接两次遍历来做这件事情

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 3000010
 5 #define pii pair <int, int>
 6 int n, fa[N], ans[N], d[N];   
 7 vector <pii> G[N];
 8 pii g[N];
 9 
10 int main()
11 {
12     while (scanf("%d", &n) != EOF)
13     {
14         for (int i = 1; i <= n; ++i) G[i].clear();
15         memset(ans, -1, sizeof ans);
16         memset(d, 0, sizeof d);
17         fa[1] = 0; 
18         for (int i = 2; i <= n; ++i)
19         {
20             scanf("%d", fa + i);
21             ++d[fa[i]];
22         }    
23         for (int v = n; v >= 1; --v)
24         {
25             int u = fa[v];
26             if (!d[v]) 
27                 G[u].push_back(pii(v, 1)); 
28             else
29             {
30                 sort(G[v].begin(), G[v].end());
31                 pii tmp = *G[v].begin();
32                 ++tmp.second;
33                 G[u].push_back(tmp);
34                 int Min = (*G[v].begin()).second;
35                 for (int i = 1, len = G[v].size(); i < len; ++i)
36                 {
37                     pii it = G[v][i];
38                     ans[it.first] = Min + it.second;
39                 }
40             }
41         }
42         for (int v = 1; v <= n; ++v)
43         {
44             g[v] = pii(1e9, 1e9);
45             int u = fa[v];
46             if (u)
47             {
48                 g[v] = g[u];
49                 ++g[v].second;
50                 pii tmp = g[v];
51                 if (tmp.first != -1) for (int i = 0, len = G[v].size(); i < len; ++i) 
52                 {
53                     pii it = G[v][i];
54                     if (it.first > tmp.first)    
55                         ans[it.first] = min(ans[it.first], it.second + tmp.second);  
56                 }
57             }
58             if (!G[v].empty())
59             {
60                 pii it = *G[v].begin();
61                 if (it.second < g[v].second)
62                     g[v] = it;
63             }
64         }
65         for (int i = 1; i <= n; ++i) if (!d[i]) printf("%d %d\n", i, ans[i]); 
66     }
67     return 0;
68 }
View Code

相关文章: