洛谷 3285 [JLOI2014]松鼠的新家

【题解】

  给出一条路径,问树上的点被经过了几次。

  显然树剖之后树上差分就好了。

  

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define N 300010
 4 #define rg register
 5 using namespace std;
 6 int n,tot,last[N],dep[N],fa[N],size[N],son[N],val[N],top[N],a[N];
 7 struct edge{
 8     int to,pre;
 9 }e[N<<1];
10 inline int read(){
11     int k=0,f=1; char c=getchar();
12     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
13     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
14     return k*f;
15 }
16 void dfs1(int x){
17     size[x]=1; dep[x]=dep[fa[x]]+1;
18     for(rg int i=last[x],to;i;i=e[i].pre) if((to=e[i].to)!=fa[x]){
19         fa[to]=x; dfs1(to);
20         size[x]+=size[to];
21         if(size[to]>size[son[x]]) son[x]=to;
22     }
23 }
24 void dfs2(int x,int tp){
25     top[x]=tp;
26     if(son[x]) dfs2(son[x],tp);
27     for(rg int i=last[x],to;i;i=e[i].pre) 
28         if((to=e[i].to)!=son[x]&&to!=fa[x]) dfs2(to,to);
29 }
30 inline int lca(int x,int y){
31     int f1=top[x],f2=top[y];
32     while(f1!=f2){
33         if(dep[f1]<dep[f2]) swap(x,y),swap(f1,f2);
34         x=fa[f1]; f1=top[x];
35     }
36     return dep[x]<dep[y]?x:y;
37 }
38 void dfs(int x){
39     for(rg int i=last[x],to;i;i=e[i].pre) if((to=e[i].to)!=fa[x]){
40         dfs(to);
41         val[x]+=val[to];
42     }
43 }
44 int main(){
45     n=read();
46     for(rg int i=1;i<=n;i++) a[i]=read();
47     for(rg int i=1;i<n;i++){
48         int u=read(),v=read();
49         e[++tot]=(edge){v,last[u]}; last[u]=tot;
50         e[++tot]=(edge){u,last[v]}; last[v]=tot;
51     }
52     dfs1(1);
53     dfs2(1,1);
54     for(rg int i=2;i<=n;i++){
55         int L=lca(a[i],a[i-1]);
56         val[a[i]]++; val[a[i-1]]++; val[L]--; val[fa[L]]--;
57         //printf("lca=%d
",L);
58     }
59     dfs(1);
60     for(rg int i=2;i<=n;i++) val[a[i]]--;
61     for(rg int i=1;i<=n;i++) printf("%d
",val[i]);
62     return 0;
63 }
View Code
原文地址:https://www.cnblogs.com/DriverLao/p/8707326.html