既然我们只知道最后数量为$k$的蚂蚁会在特殊边上被吃掉,不妨逆着推回去,然后到达每个叶节点的时候就会有一个被吃掉的蚂蚁的区间,然后二分一下就好啦
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=1000005,maxx=1e9; 6 int ant[N],deg[N],leaf[N]; 7 int p[N],noww[2*N],goal[2*N]; 8 int n,g,k,t,root,t1,t2,n1,n2,cnt; 9 long long ans; 10 void link(int f,int t) 11 { 12 noww[++cnt]=p[f]; 13 goal[cnt]=t,p[f]=cnt; 14 } 15 void DFS(int nde,int fth,long long l,long long r) 16 { 17 if(l>maxx) return ; if(r>maxx) r=maxx; 18 for(int i=p[nde];i;i=noww[i]) 19 if(goal[i]!=fth) 20 t=deg[goal[i]]-1,DFS(goal[i],nde,l*t,r*t+t-1); 21 if(leaf[nde]) 22 ans+=(upper_bound(ant+1,ant+1+g,r)-lower_bound(ant+1,ant+1+g,l))*k; 23 } 24 int main () 25 { 26 scanf("%d%d%d",&n,&g,&k); 27 for(int i=1;i<=g;i++) 28 scanf("%d",&ant[i]); 29 sort(ant+1,ant+1+g); 30 scanf("%d%d",&n1,&n2); 31 link(n1,n2),link(n2,n1); 32 deg[n1]++,deg[n2]++; 33 for(int i=2;i<n;i++) 34 { 35 scanf("%d%d",&t1,&t2); 36 link(t1,t2),link(t2,t1); 37 deg[t1]++,deg[t2]++; 38 } 39 for(int i=1;i<=n;i++) if(deg[i]==1) deg[i]=2,leaf[i]=true; 40 root=n1,DFS(n1,n2,k*(deg[n1]-1),k*(deg[n1]-1)+deg[n1]-2); 41 root=n2,DFS(n2,n1,k*(deg[n2]-1),k*(deg[n2]-1)+deg[n2]-2); 42 printf("%lld",ans); 43 return 0; 44 }