解题:POI 2014 Ant colony

题面

既然我们只知道最后数量为$k$的蚂蚁会在特殊边上被吃掉,不妨逆着推回去,然后到达每个叶节点的时候就会有一个被吃掉的蚂蚁的区间,然后二分一下就好啦

 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 }
View Code
原文地址:https://www.cnblogs.com/ydnhaha/p/9809433.html