3872: [Poi2014]Ant colony

Time Limit: 30 Sec  Memory Limit: 128 MB

Description

 
There is an entrance to the ant hill in every chamber with only one corridor leading into (or out of) it. At each entry, there are g groups of m1,m2,...,mg ants respectively. These groups will enter the ant hill one after another, each successive group entering once there are no ants inside. Inside the hill, the ants explore it in the following way:
Upon entering a chamber with d outgoing corridors yet unexplored by the group, the group divides into d groups of equal size. Each newly created group follows one of the d corridors. If d=0, then the group exits the ant hill.
If the ants cannot divide into equal groups, then the stronger ants eat the weaker until a perfect division is possible. Note that such a division is always possible since eventually the number of ants drops down to zero. Nothing can stop the ants from allowing divisibility - in particular, an ant can eat itself, and the last one remaining will do so if the group is smaller than d.
The following figure depicts m ants upon entering a chamber with three outgoing unexplored corridors, dividing themselves into three (equal) groups of floor(m/3) ants each.
A hungry anteater dug into one of the corridors and can now eat all the ants passing through it. However, just like the ants, the anteater is very picky when it comes to numbers. It will devour a passing group if and only if it consists of exactly k ants. We want to know how many ants the anteater will eat.
给定一棵有n个节点的树。在每个叶子节点,有g群蚂蚁要从外面进来,其中第i群有m[i]只蚂蚁。这些蚂蚁会相继进入树中,而且要保证每一时刻每个节点最多只有一群蚂蚁。这些蚂蚁会按以下方式前进:
·在即将离开某个度数为d+1的点时,该群蚂蚁有d个方向还没有走过,这群蚂蚁就会分裂成d群,每群数量都相等。如果d=0,那么蚂蚁会离开这棵树。
·如果蚂蚁不能等分,那么蚂蚁之间会互相吞噬,直到可以等分为止,即一群蚂蚁有m只,要分成d组,每组将会有floor(m/d)只,如下图。
 
一只饥饿的食蚁兽埋伏在一条边上,如果有一群蚂蚁通过这条边,并且数量恰为k只,它就会吞掉这群蚂蚁。请计算一共有多少只蚂蚁会被吞掉。
 

Input

The first line of the standard input contains three integers n, g, k (2<=n,g<=1000000, 1<=k<=10^9), separated by single spaces. These specify the number of chambers, the number of ant groups and the number of ants the anteater devours at once. The chambers are numbered from 1 to n.
The second line contains g integers m[1],m[2],...,m[g](1<=m[i]<=10^9), separated by single spaces, where m[i] gives the number of ants in the i-th group at every entrance to the ant hill. The n-1 lines that follow describe the corridors within the ant hill; the i-th such line contains two integers a[i],b[i] (1<=a[i],b[i]<=n), separated by a single space, that indicate that the chambers no.a[i] and b[i] are linked by a corridor. The anteater has dug into the corridor that appears first on input.
第一行包含三个整数n,g,k,表示点数、蚂蚁群数以及k。
第二行包含g个整数m[1],m[2],...,m[g],表示每群蚂蚁中蚂蚁的数量。
接下来n-1行每行两个整数,表示一条边,食蚁兽埋伏在输入的第一条边上。
 

Output

Your program should print to the standard output a single line containing a single integer: the number of ants eaten by the anteater.
一个整数,即食蚁兽能吃掉的蚂蚁的数量。
 

Sample Input

7 5 3
3 4 1 9 11
1 2
1 4
4 3
4 5
4 6
6 7

Sample Output

21

HINT

显然得从那条关键边倒着推

以这条边作为这棵树的“根”,开始遍历其他的边,遍历到每条边的时候计算一下“到这条边时这群蚂蚁会被吃掉”的当时蚂蚁数量上限和下限

然后对于每个叶子节点的那些边,二分一下有多少组蚂蚁会被吃掉就好了

#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define N 1000010
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
ll lj[N],fro[N<<],to[N<<],du[N],cnt,s1,s2;
inline void add(int a,int b){to[++cnt]=b;fro[cnt]=lj[a];lj[a]=cnt;du[a]++;}
ll mn[N],mx[N],n,g,k,m[N],u,v,ans;
void dfs(int x,int f)
{
int v;
for(int i=lj[x];i;i=fro[i])
{
v=to[i];
if(v==f) continue;
mn[v]=mn[x]*(du[x]-);
mx[v]=mx[x]*(du[x]-)+du[x]-;
mx[v]=min(mx[v],m[g]);
if(mn[v]<=m[g]) dfs(v,x);
}
}
ll cal(ll x)
{
ll L=,R=g+,mid;
while(L<R)
{
mid=(L+R)>>;
if(m[mid]<=x) L=mid+;
else R=mid;
}
return L-;
}
int main()
{
n=read();g=read();k=read();
for(int i=;i<=g;i++) m[i]=read();
sort(m+,m+g+);
s1=read();s2=read();
add(s1,s2);add(s2,s1);
for(int i=;i<n;i++)
{
u=read();v=read();
add(u,v);add(v,u);
}
mn[s1]=mn[s2]=mx[s1]=mx[s2]=k;
dfs(s1,s2);dfs(s2,s1);
for(int i=;i<=n;i++) if(du[i]==) ans+=cal(mx[i])-cal(mn[i]-);
printf("%lld\n",ans*k);
return ;
}

bzoj 3872: [Poi2014]Ant colony -- 树形dp+二分的更多相关文章

  1. 【BZOJ3872】[Poi2014]Ant colony 树形DP+二分

    [BZOJ3872][Poi2014]Ant colony Description 给定一棵有n个节点的树.在每个叶子节点,有g群蚂蚁要从外面进来,其中第i群有m[i]只蚂蚁.这些蚂蚁会相继进入树中, ...

  2. bzoj 3872: [Poi2014]Ant colony【树形dp+二分】

    啊我把分子分母混了WA了好几次-- 就是从食蚁兽在的边段成两棵树,然后dp下去可取的蚂蚁数量区间,也就是每次转移是l[e[i].to]=l[u](d[u]-1),r[e[i].to]=(r[u]+1) ...

  3. bzoj 3872 [Poi2014]Ant colony——二分答案

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3872 可以倒推出每个叶子节点可以接受的值域.然后每个叶子二分有多少个区间符合即可. 注意一开 ...

  4. [bzoj3872][Poi2014]Ant colony_树形dp

    Ant colony bzoj-3872 Poi-2014 题目大意:说不明白.....题目链接 注释:略. 想法:两个思路都行. 反正我们就是要求出每个叶子节点到根节点的每个路径权值积. 可以将边做 ...

  5. bzoj 3420: Poi2013 Triumphal arch 树形dp+二分

    给一颗树,$1$ 号节点已经被染黑,其余是白的,两个人轮流操作,一开始 $B$ 在 $1$ 号节点,$A$ 选择 $k$ 个点染黑,然后 $B$ 走一步,如果 $B$ 能走到 $A$ 没染的节点则 $ ...

  6. [BZOJ3872][Poi2014]Ant colony

    [BZOJ3872][Poi2014]Ant colony 试题描述 There is an entrance to the ant hill in every chamber with only o ...

  7. [BZOJ 4033] [HAOI2015] T1 【树形DP】

    题目链接:BZOJ - 4033 题目分析 使用树形DP,用 f[i][j] 表示在以 i 为根的子树,有 j 个黑点的最大权值. 这个权值指的是,这个子树内部的点对间距离的贡献,以及 i 和 Fat ...

  8. 两种解法-树形dp+二分+单调队列(或RMQ)-hdu-4123-Bob’s Race

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4123 题目大意: 给一棵树,n个节点,每条边有个权值,从每个点i出发有个不经过自己走过的点的最远距离 ...

  9. [BZOJ 4455] [ZJOI 2016] 小星星 (树形dp+容斥原理+状态压缩)

    [BZOJ 4455] [ZJOI 2016] 小星星 (树形dp+容斥原理+状态压缩) 题面 给出一棵树和一个图,点数均为n,问有多少种方法把树的节点标号,使得对于树上的任意两个节点u,v,若树上u ...

随机推荐

  1. vue登录/查看/结束端口号

    下班时间到啦! --下班都是他们的,而我,还是什么都没有. vue登录(未登录情况下不允许进入) 在路由里加上登录的权限 meta: { requireAuth: true, title: 'Logi ...

  2. docker安装总结 linux红帽系列

    由于Docker限制分为两个版本CE和EE,所以之前yum里面的docker是老版本,需要先进行卸载,现在的包名叫做docker-ce yum remove docker docker-common ...

  3. LDA线性判别分析

    LDA线性判别分析 给定训练集,设法将样例投影到一条直线上,使得同类样例的投影点尽可能的近,异类样例点尽可能的远,对新样本进行分类的时候,将新样本同样的投影,再根据投影得到的位置进行判断,这个新样本的 ...

  4. inet_addr_onlink

    /* 根据指定设备的ip配置块,判断地址a,b是否在同一子网 */ /* --邻居项要求,在同一子网中的两个设备, 至少有一个接口有相同的子网配置, --也就是说对端的in_dev->ifa_l ...

  5. C++——map注意事项

    1. C++标准模块库STL中提供了两种基本的关联容器:set和map.其内部实现是都是采用红黑树,但不同的是,set中结点存储的是键值,map中结点存储的是<key,value>的键值对 ...

  6. C/C++——[03] 注释

    C/C++源程序中被注释的内容不能被编译,被认为是不属于程序的一部分. C/C++的注释有两种写法: 多行注释:以 “ /*”开头,以“ */”结尾: #include <stdio.h> ...

  7. Window文本在Linux中出现的^M问题

    问题:在Windows中写了一个shell脚本在Linux中死活不能运行,怎么也查不出错误,原来是格式问题. 原因:Windows/DOS系统的换行符是/r/n,Unix/Linux系统的换行符是/n ...

  8. SLD 官方实例

    基于xml标准的sld格式: <?xml version="1.0" encoding="UTF-8"?> <StyledLayerDescr ...

  9. Codeforces 776C - Molly's Chemicals(思维+前缀和)

    题目大意:给出n个数(a1.....an),和一个数k,问有多少个区间的和等于k的幂 (1 ≤ n ≤ 10^5, 1 ≤ |k| ≤ 10, - 10^9 ≤ ai ≤ 10^9) 解题思路:首先, ...

  10. bzoj 1224

    dfs + 剪枝, 用最大最小值剪. #include<bits/stdc++.h> #define LL long long #define fi first #define se se ...