欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

luogu P3576 [POI2014]MRO-Ant colony

程序员文章站 2022-07-13 12:40:39
...

传送门

一群蚂蚁能被吃,也就是走到指定边的两端点之一要走到另一端点时有\(k\)只,我们可以从这两端点逆推,记两个值为走到某个点时最后会被吃掉\(k\)只蚂蚁的蚂蚁数量范围,式子下面有,很好理解(雾).最后在每个叶子节点二分查找有多少个数在区间内即可

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define LL long long
#define il inline
#define re register
#define inf 2099999999
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define db double
#define eps (1e-5)

using namespace std;
const int N=1000000+10;
il LL rd()
{
    re LL x=0,w=1;re char ch=0;
    while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}
LL d[N];
int to[N<<1],nt[N<<1],hd[N],tot=1;
il void add(int x,int y)
{
  ++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot,++d[x];
  ++tot,to[tot]=x,nt[tot]=hd[y],hd[y]=tot,++d[y];
}
int n,g,k,ma,xx,yy;
LL ll[N],rr[N],ans,a[N];
void dfs(int x,int ffa)
{
  for(int i=hd[x];i;i=nt[i])
    {
      int y=to[i];
      if(y==ffa) continue;
      ll[y]=min(ll[x]*max(d[x]-1,1ll),a[g]+10),rr[y]=min((rr[x]+1)*max(d[x]-1,1ll)-1,a[g]+10);
      dfs(y,x);
    }
  if(d[x]==1)
    {
      int l=0,r=g,z=g,zz=0;
      while(l<=r)
        {
          int mid=(l+r)>>1;
          if(a[mid]<ll[x]) z=mid,l=mid+1;
          else r=mid-1;
        }
      l=0,r=g;
      while(l<=r)
        {
          int mid=(l+r)>>1;
          if(a[mid]<=rr[x]) zz=mid,l=mid+1;
          else r=mid-1;
        }
      ans+=max(zz-z,0);
    }
}

int main()
{
  n=rd(),g=rd(),k=rd();
  for(int i=1;i<=g;i++) a[i]=rd();
  sort(a+1,a+g+1);
  a[0]=-1;
  add(xx=rd(),yy=rd());
  for(int i=2;i<n;i++) add(rd(),rd());
  ll[xx]=rr[xx]=k,dfs(xx,yy);
  ll[yy]=rr[yy]=k,dfs(yy,xx);
  printf("%lld\n",ans*k);
  return 0;
}