洛谷 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\n",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\n",val[i]); 62 return 0; 63 }