由于蚂蚁没有办法走回头路(概率DP),所以答案是唯一的,并有点像树形DP
正难则反,观察到每群蚂蚁的终点是一定的,可以从终点DP
由整除的性质可以发现,每个点能被食蚁兽吃掉的蚂蚁数是一个区间
所以DP维护每个叶子节点的答案区间,二分统计蚂蚁群数
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+5;
int cnt,to[N<<1],nxt[N<<1],he[N],R[N],L[N],son[N],a[N],n,m,k;
ll ans;
inline void add(int u,int v) {
to[++cnt]=v,nxt[cnt]=he[u],he[u]=cnt;
}
inline void dp(int u,int siz,int l,int r) {
if((ll)siz*l>a[m]) return;
L[u]=siz*l;
if((ll)siz*(r+1)-1>a[m]) R[u]=a[m];
else R[u]=siz*(r+1)-1;
}
void dfs(int fa,int u) {
for(int e=he[u];e;e=nxt[e]) {
int v=to[e];
if(v!=fa) {
dp(v,(son[v]==0?1:son[v]),L[u],R[u]);
if(L[v]!=0||R[v]!=0) {
dfs(u,v);
}
}
}
}
inline int left(int x) {
int l=1,r=m,ans;
while(l<=r) {
int mid=l+r>>1;
if(a[mid]>=x) ans=mid,r=mid-1;
else l=mid+1;
}
return ans;
}
inline int right(int x) {
int l=1,r=m,ans=0;
while(l<=r) {
int mid=l+r>>1;
if(a[mid]<=x) ans=mid,l=mid+1;
else r=mid-1;
}
return ans;
}
int main() {
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;i++) {
scanf("%d",&a[i]);
}
sort(a+1,a+m+1);
int rt=0,Fa=0;
for(int i=1;i<n;i++) {
int u,v; scanf("%d%d",&u,&v);
add(u,v),add(v,u);
son[u]++,son[v]++;
if(i==1) {
rt=u,Fa=v;
}
}
for(int i=1;i<=n;i++) son[i]--;
dp(rt,(son[rt]==0?1:son[rt]),k,k);
dp(Fa,(son[Fa]==0?1:son[Fa]),k,k);
dfs(Fa,rt),dfs(rt,Fa);
for(int i=1;i<=n;i++) {
// if(!son[i]) printf("%d %d\n",L[i],R[i]);
if(!son[i]&&(L[i]||R[i])) {
ans+=right(R[i])-left(L[i])+1;
}
}
printf("%lld\n",ans*k);
return 0;
}
Luogu P3576 [POI2014]MRO-Ant colony
原文:https://www.cnblogs.com/wsfwsf/p/13573286.html