BZOJ3872 : [Poi2014]Ant colony
设i点的度数为d[i]
则如果有x只蚂蚁在从i走到别处,会分裂成每群$\lfloor\frac{x}{d[i]-1}\rfloor$只蚂蚁
对于x出发的m只蚂蚁,到y处还剩$\lfloor\frac{m}{x到y路径上所有点度数-1的乘积}\rfloor$
于是我们一遍DFS求出到每个叶子节点时一路上点度数-1的乘积,再在数组中二分查找出一个合法的区间即可
#include<cstdio> #include<algorithm> #define N 1000010 typedef long long ll; int n,m,k,i,j,x,y,g[N],nxt[N<<1],v[N<<1],d[N],ed,a[N];ll ans; inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';} inline void add(int x,int y){d[x]++;v[++ed]=y;nxt[ed]=g[x];g[x]=ed;} inline int ask(ll x){ if(x>a[m])return m; if(x<=a[1])return 0; int l=1,r=m,t,mid; while(l<=r)if(a[mid=(l+r)>>1]<x)l=(t=mid)+1;else r=mid-1; return t; } void dfs(int x,int y,int t){ if(!d[x])ans+=ask((ll)(k+1)*t)-ask((ll)k*t); if((ll)t*d[x]>a[m])return;t*=d[x]; for(int i=g[x];i;i=nxt[i])if(i>2&&v[i]!=y)dfs(v[i],x,t); } int main(){ read(n),read(m),read(k); for(i=1;i<=m;i++)read(a[i]); std::sort(a+1,a+m+1); for(i=1;i<n;i++)read(x),read(y),add(x,y),add(y,x); for(i=1;i<=n;i++)d[i]--; dfs(v[1],0,1);dfs(v[2],0,1); return printf("%lld",ans*k),0; }