码迷,mamicode.com
首页 > 其他好文 > 详细

[树上差分][lca] Luogu P3258 松鼠的新家

时间:2019-08-11 10:26:10      阅读:75      评论:0      收藏:0      [点我收藏+]

标签:之间   fine   color   for   efi   mes   from   糖果   ring   

题目描述

松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在”树“上。

松鼠想邀请小熊维尼前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去a1,再去a2,......,最后到an,去参观新家。可是这样会导致维尼重复走很多房间,懒惰的维尼不停地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。

维尼是个馋家伙,立马就答应了。现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。

因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。

 

题解

  • 就是一道比较裸的树上差分题目

 

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #define N 300010
 5 using namespace std;
 6 struct edge{ int to,from,v; }e[N*2];
 7 int n,cnt,head[N],f[40][N],deep[N],a[N],cf[N],vis[N];
 8 void insert(int x,int y)
 9 {
10     e[++cnt].to=y,e[cnt].from=head[x],head[x]=cnt;
11     e[++cnt].to=x,e[cnt].from=head[y],head[y]=cnt;
12 }
13 int lca(int x,int y)
14 {
15     if (deep[x]<deep[y]) swap(x,y);
16     for (int i=30;i>=0;i--) if (deep[f[i][x]]>=deep[y]) x=f[i][x];
17     if (x==y) return x;
18     for (int i=30;i>=0;i--) if (f[i][x]!=f[i][y]) x=f[i][x],y=f[i][y];
19     return f[0][x];
20 }
21 void dfs(int x,int fa)
22 {
23     f[0][x]=fa,deep[x]=deep[fa]+1;
24     for (int i=head[x];i;i=e[i].from) if (e[i].to!=fa) dfs(e[i].to,x);
25 }
26 int dfs1(int x)
27 {
28     int ans=cf[x]; vis[x]=1;
29     for (int i=head[x];i;i=e[i].from) if (!vis[e[i].to]) ans+=(e[i].v=dfs1(e[i].to));
30     for (int i=head[x];i;i=e[i].from) if (e[i].to==f[0][x]) e[i].v=ans,i=0;
31     return ans;
32 }
33 int main()
34 {
35     scanf("%d",&n);
36     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
37     for (int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),insert(x,y);
38     dfs(a[1],a[1]);
39     for (int i=1;(1<<i)<=n;i++) for (int j=1;j<=n;j++) f[i][j]=f[i-1][f[i-1][j]];
40     for (int i=1;i<n;i++)  cf[a[i]]++,cf[a[i+1]]++,cf[lca(a[i],a[i+1])]-=2;
41     memset(vis,0,sizeof(vis)),dfs1(a[1]);
42     for (int i=1;i<=n;i++)
43     {
44         int ans=0;
45         for (int j=head[i];j;j=e[j].from) ans+=e[j].v;
46         if (i==a[n]) ans--; printf("%d\n",(ans+1)/2);
47     }
48 }

 

[树上差分][lca] Luogu P3258 松鼠的新家

标签:之间   fine   color   for   efi   mes   from   糖果   ring   

原文地址:https://www.cnblogs.com/Comfortable/p/11333974.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!