P3258 [JLOI2014]松鼠的新家

原题链接

考察:树上差分

思路:

       点差分.区别在于中间点多+了1.注意不能在dfs前对差分数组-1.这样会导致递推错误.比如下图:

 1 #include <iostream>
 2 #include <cstring>
 3 #include <queue>
 4 using namespace std;
 5 const int N = 300050;
 6 typedef long long LL;
 7 int n,r[N],h[N],idx,d[N],depth[N],fa[N][20];
 8 struct Road{
 9     int fr,to,ne;
10 }road[N<<1];
11 void add(int a,int b)
12 {
13     road[idx].fr = a,road[idx].to = b,road[idx].ne = h[a],h[a] = idx++;
14 }
15 void bfs(int s)
16 {
17     queue<int> q;
18     q.push(s);
19     memset(depth,0x3f,sizeof depth);
20     depth[s] = 1,depth[0] = 0;
21     while(q.size())
22     {
23         int u = q.front();
24         q.pop();
25         for(int i=h[u];~i;i=road[i].ne)
26         {
27             int v = road[i].to;
28             if(depth[v]>depth[u]+1)
29             {
30                 depth[v] = depth[u]+1;
31                 q.push(v);
32                 fa[v][0] = u;
33                 for(int j=1;j<=19;j++)
34                  fa[v][j] = fa[fa[v][j-1]][j-1];
35             }
36         }
37     }
38 }
39 int lca(int a,int b) 
40 {
41     if(depth[a]<depth[b]) swap(a,b);
42     for(int j=19;j>=0;j--)
43       if(depth[fa[a][j]]>=depth[b]) a = fa[a][j];
44     if(a==b) return a;
45     for(int j=19;j>=0;j--)
46       if(fa[a][j]!=fa[b][j]) a = fa[a][j],b = fa[b][j];
47     return fa[a][0];
48 }
49 void dfs(int u,int fa)
50 {
51     for(int i=h[u];~i;i=road[i].ne)
52     {
53         int v = road[i].to;
54         if(v==fa) continue;
55         dfs(v,u);
56         d[u]+=d[v];
57     }
58 }
59 int main()
60 {
61     scanf("%d",&n);
62     for(int i=1;i<=n;i++) scanf("%d",&r[i]),h[i] = -1; 
63     for(int i=1;i<n;i++)
64     {
65         int a,b; scanf("%d%d",&a,&b);
66         add(a,b); add(b,a);
67     }
68     bfs(1);
69     for(int i=2;i<=n;i++)
70     {
71         int a = r[i-1],b = r[i];
72         int anc = lca(a,b);
73         d[a]++,d[b]++,d[anc]--,d[fa[anc][0]]--;
74     }
75     dfs(1,-1);
76     for(int i=2;i<=n;i++)  d[r[i]]--;
77     for(int i=1;i<=n;i++) printf("%d\n",d[i]);
78     return 0;
79 }

 

posted @ 2021-05-12 09:39  acmloser  阅读(53)  评论(0编辑  收藏  举报