[JLOI 2014]松鼠的新家
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
题解
裸的树上差分。
我们将一条路径如$u->v$,
我们需要将标记数组:
$$cnt[u]++,cnt[v]++,cnt[lca(u,v)]--,cnt[fa[lca(u,v)][0]]--$$
最后上传标记即可,正确性可以画图推一下。
但注意由于这样做会将每个点重复计算一次(上一条路径的结尾,这一条路径的起始)
我们需要将每个点点权再$-1$,
注意由于第一条路径起始点是要计算的,我们还要加回来。
1 #include<set> 2 #include<map> 3 #include<ctime> 4 #include<cmath> 5 #include<queue> 6 #include<stack> 7 #include<vector> 8 #include<cstdio> 9 #include<string> 10 #include<cstring> 11 #include<cstdlib> 12 #include<iostream> 13 #include<algorithm> 14 #define LL long long 15 #define Max(a,b) ((a)>(b) ? (a):(b)) 16 #define Min(a,b) ((a)<(b) ? (a):(b)) 17 using namespace std; 18 const int N=300000; 19 20 int n,u,v,lim; 21 struct tt 22 { 23 int to,next; 24 }edge[N*2+5]; 25 int path[N+5],top; 26 void Add(int u,int v); 27 int a[N+5]; 28 29 int dep[N+5],fa[N+5][20]; 30 void Dfs(int r,int depth); 31 void RMQ(); 32 int lca(int a,int b); 33 34 int cnt[N+5]; 35 void Dfs2(int r); 36 37 int main() 38 { 39 scanf("%d",&n); 40 lim=log(n)/log(2); 41 for (int i=1;i<=n;i++) scanf("%d",&a[i]); 42 for (int i=1;i<n;i++) 43 { 44 scanf("%d%d",&u,&v); 45 Add(u,v); 46 Add(v,u); 47 } 48 Dfs(1,1); 49 RMQ(); 50 for (int i=1;i<n;i++) 51 { 52 int w=lca(a[i],a[i+1]); 53 cnt[a[i]]++,cnt[a[i+1]]++,cnt[w]--,cnt[fa[w][0]]--; 54 } 55 Dfs2(1); 56 cnt[a[1]]++; 57 for (int i=1;i<=n;i++) printf("%d\n",cnt[i]-1); 58 return 0; 59 } 60 61 void Add(int u,int v) 62 { 63 edge[++top].to=v; 64 edge[top].next=path[u]; 65 path[u]=top; 66 } 67 void Dfs(int r,int depth) 68 { 69 dep[r]=depth; 70 for (int i=path[r];i;i=edge[i].next) 71 if (!dep[edge[i].to]) 72 { 73 fa[edge[i].to][0]=r; 74 Dfs(edge[i].to,depth+1); 75 } 76 } 77 void RMQ() 78 { 79 for (int t=1;t<=lim;t++) 80 for (int i=1;i<=n;i++) 81 fa[i][t]=fa[fa[i][t-1]][t-1]; 82 } 83 int lca(int a,int b) 84 { 85 if (dep[a]<dep[b]) swap(a,b); 86 for (int i=lim;i>=0;i--) if (dep[fa[a][i]]>=dep[b]) a=fa[a][i]; 87 if (a!=b) 88 { 89 for (int i=lim;i>=0;i--) if (fa[a][i]!=fa[b][i]) a=fa[a][i],b=fa[b][i]; 90 a=fa[a][0],b=fa[b][0]; 91 } 92 return a; 93 } 94 void Dfs2(int r) 95 { 96 for (int i=path[r];i;i=edge[i].next) 97 if (edge[i].to!=fa[r][0]) 98 { 99 Dfs2(edge[i].to); 100 cnt[r]+=cnt[edge[i].to]; 101 } 102 }
博主蒟蒻,随意转载。但必须附上原文链接:http://www.cnblogs.com/NaVi-Awson/,否则你会终生找不到妹子!!!