【JLOI2014】松鼠的新家

题面

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

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

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

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

2<= n <=300000

分析

很明显的树上点差分,但是直接标记不太对,因为会有既是起点又是终点的点被标记两次。

我们只需要将差分的子树和求出来后在ans里对2~n-1个点每个点减一,由于最后一个点是餐厅,所以也也减一。

代码

  1. #include<bits/stdc++.h>  
  2. using namespace std;  
  3. #define N 300030  
  4. int n,cnt;  
  5. int a[N],c[N],ans[N],dep[N],first[N],fa[N][20];  
  6. struct email  
  7. {  
  8.     int u,v;  
  9.     int nxt;  
  10. }e[N*4];  
  11. inline void add(int u,int v)  
  12. {  
  13.     e[++cnt].nxt=first[u];first[u]=cnt;  
  14.     e[cnt].u=u;e[cnt].v=v;  
  15. }  
  16. template<class T>  
  17. inline void read(T &x)  
  18. {  
  19.     x=0;int f=1;static char c=getchar();   
  20.     while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}  
  21.     while(c>='0'&&c<='9'){x=x*10+c-'0',c=getchar();}  
  22.     x*=f;  
  23. }  
  24. inline void pre(int u,int f)  
  25. {  
  26.     for(int i=1;(1<<i)<=dep[u];i++)  
  27.         fa[u][i]=fa[fa[u][i-1]][i-1];  
  28.     for(int i=first[u];i;i=e[i].nxt)  
  29.     {  
  30.         int v=e[i].v;  
  31.         if(v==f)continue;  
  32.         dep[v]=dep[u]+1;  
  33.         fa[v][0]=u;  
  34.         pre(v,u);  
  35.     }  
  36. }  
  37.   
  38. inline int lca(int x,int y)  
  39. {  
  40.     if(dep[x]<dep[y])swap(x,y);  
  41.     int t=dep[x]-dep[y];  
  42.     for(int i=0;(1<<i)<=t;i++)  
  43.         if((1<<i)&t)  
  44.             x=fa[x][i];  
  45.     if(x==y)return x;  
  46.     for(int i=19;i>=0;i--)  
  47.         if(fa[x][i]!=fa[y][i])  
  48.             x=fa[x][i],y=fa[y][i];  
  49.     return fa[x][0];  
  50. }   
  51.   
  52. inline void dfs(int u,int f)  
  53. {  
  54.     for(int i=first[u];i;i=e[i].nxt)  
  55.     {  
  56.         int v=e[i].v;  
  57.         if(v==f)continue;  
  58.         dfs(v,u);  
  59.         c[u]+=c[v];   
  60.     }  
  61.     ans[u]=c[u];  
  62. }  
  63.   
  64. int main()  
  65. {  
  66.     read(n);  
  67.     for(int i=1;i<=n;i++)read(a[i]);  
  68.     for(int i=1;i<n;i++)  
  69.     {  
  70.         int u,v;  
  71.         read(u),read(v);  
  72.         add(u,v);add(v,u);  
  73.     }   
  74.     pre(1,0);  
  75.     for(int i=1;i<n;i++)  
  76.     {  
  77.         int u=a[i],v=a[i+1],LCA=lca(u,v);  
  78.         c[u]++,c[v]++,c[LCA]--,c[fa[LCA][0]]--;  
  79.     }  
  80.     dfs(1,0);  
  81.     for(int i=2;i<=n;i++)ans[a[i]]--;  
  82.     for(int i=1;i<=n;i++)printf("%d ",ans[i]);;  
  83.     return 0;  
  84. }  
原文地址:https://www.cnblogs.com/NSD-email0820/p/9854267.html