[BZOJ3872][Poi2014]Ant colony

试题描述

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只,它就会吞掉这群蚂蚁。请计算一共有多少只蚂蚁会被吞掉。

输入

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行每行两个整数,表示一条边,食蚁兽埋伏在输入的第一条边上。

输出

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

输入示例


输出示例


数据规模及约定

见“输入

题解

因为只有一只食蚁兽,所以可以从它所在的边开始 BFS,求出每条边经过的蚂蚁上限和下限,扩展到叶节点后二分找有几群蚂蚁在下界和上界范围内累计答案即可。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std; const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *Tail;
inline char Getchar() {
if(Head == Tail) {
int l = fread(buffer, 1, BufferSize, stdin);
Tail = (Head = buffer) + l;
}
return *Head++;
}
int read() {
int x = 0, f = 1; char c = Getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
return x * f;
} #define maxn 1000010
#define maxm 2000010
#define LL long long
int n, g, k, m, head[maxn], next[maxm], to[maxm], ind[maxn];
LL ants[maxn], mxa; void AddEdge(int a, int b) {
to[++m] = b; next[m] = head[a]; head[a] = m;
swap(a, b);
to[++m] = b; next[m] = head[a]; head[a] = m;
return ;
} bool vis[maxn];
int Q[maxn], hd, tl;
LL low[maxn], upp[maxn];
void BFS(int s) {
hd = tl = 0; Q[++tl] = s;
while(hd < tl) {
int u = Q[++hd];
// printf("%d %lld %lld\n", u, low[u], upp[u]);
for(int e = head[u]; e; e = next[e]) if(!vis[to[e]]) {
Q[++tl] = to[e]; vis[to[e]] = 1;
if(low[u] * ((LL)ind[u] - 1) > mxa) low[to[e]] = mxa + 1;
else low[to[e]] = low[u] * ((LL)ind[u] - 1);
if(upp[u] * ((LL)ind[u] - 1) + ind[u] - 2 > mxa) upp[to[e]] = mxa + 1;
else upp[to[e]] = upp[u] * ((LL)ind[u] - 1) + ind[u] - 2;
}
}
return ;
} int main() {
// freopen("data.in", "r", stdin);
// freopen("data.out", "w", stdout);
n = read(); g = read(); k = read();
for(int i = 1; i <= g; i++) ants[i] = read(), mxa = max(mxa, ants[i]); int sta, stb;
for(int i = 1; i < n; i++) {
int a = read(), b = read();
AddEdge(a, b);
ind[a]++; ind[b]++;
if(i == 1) sta = a, stb = b;
}
vis[sta] = vis[stb] = 1;
low[sta] = low[stb] = upp[sta] = upp[stb] = (LL)k;
BFS(sta);
BFS(stb); sort(ants + 1, ants + g + 1);
LL ans = 0;
// for(int i = 1; i <= n; i++) if(ind[i] == 1) printf("%d: %lld %lld\n", i, low[i], upp[i]);
for(int i = 1; i <= n; i++) if(ind[i] == 1) {
int l = lower_bound(ants + 1, ants + g + 1, low[i]) - ants;
int r = upper_bound(ants + 1, ants + g + 1, upp[i]) - ants;
if(r > g || ants[r] > upp[i]) r--;
ans += (LL)(r - l + 1);
// printf("leaves: %d %d %d\n", i, l, r);
}
ans *= (LL)k;
printf("%lld", ans); return 0;
}

[BZOJ3872][Poi2014]Ant colony的更多相关文章

  1. $bzoj3872\ [Poi2014]\ Ant\ colony$ 二分+$dp$

    正解:二分+$dp$ 解题报告: 传送门$QwQ$ 一年过去了依然没有头绪,,,$gql$的$NOIp$必将惨败了$kk$. 考虑倒推,因为知道知道除数和答案,所以可以推出被除数的范围,然后一路推到叶 ...

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

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

  3. 【BZOJ3872】Ant colony(二分,动态规划)

    [BZOJ3872]Ant colony(二分,动态规划) 题面 又是权限题... Description There is an entrance to the ant hill in every ...

  4. bzoj 3872: [Poi2014]Ant colony -- 树形dp+二分

    3872: [Poi2014]Ant colony Time Limit: 30 Sec  Memory Limit: 128 MB Description   There is an entranc ...

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

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

  6. [POI2014]Ant colony

    题目大意: 给定一棵$n(n\le10^6)$个结点的树.在每个叶子结点,有$g$群蚂蚁要从外面进来,其中第$i$群有$m_i$只蚂蚁.这些蚂蚁依次爬树(一群蚂蚁爬完后才会爬另一群),若当前经过结点度 ...

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

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

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

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

  9. Luogu3576 POI2014 MRO-Ant colony 【树形DP】*

    Luogu3576 POI2014 MRO-Ant colony The ants are scavenging an abandoned ant hill in search of food. Th ...

随机推荐

  1. tsql的奇特语法

    也许是离开t-sql太久了,突然发现很多t-sql的奇特语法 用一句sql解决多种排序: ; SELECT C1, C2 FROM T ORDER BY THEN C1 END ASC, THEN C ...

  2. 工作的思考十五:升职前需要做的准备(TeamLeader)

    当一个人在公司的工作年限以及经验的积累到达一个程度的时候,升职其实是件高兴的事,但面临角色的转变需要提前做些准备的. 其实如果你对你的职业规划很清楚的话,那么你就应该在升职之前就会开始进行角色的转换. ...

  3. DOM(四)事件流

    1.冒泡型事件 浏览器的事件模型分两种:捕获型事件和冒泡型事件.由于ie不支持捕获型事件,所以以下主要以冒泡型事件作为讲解.(dubbed bubbling)冒泡型指事件安装最特定的事件到最不特定的事 ...

  4. linux 查看服务器性能常用命令

    一.top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器   下面详细介绍它的使用方法.top是一个动态显示过程,即可以通过用户按键来 ...

  5. Go-MySQL-Driver:一个Go语言的轻量级极速的mysql驱动

    Go语言的 database/sql 包的一个 MySQL驱动. 特性 轻量级与快速 原生Go语言,没有C绑定,只有纯Go 没有不安全的操作(类型转换等) 动态处理崩溃的连接 动态连接池 支持大于16 ...

  6. c#中的protected和internal

    protected限制子类访问,可以跨程序集 internal 限制此程序集访问,可以跨类 protected internal 限制此程序集的子类中访问

  7. Daily Scrum – 1/19

    Meeting Minutes 绑定了快捷键: 改良了user course: 修了一系列Bug: 准备进行演示 Progress   part 组员 今日工作 Time (h) 明日计划 Time ...

  8. photoshop将psd导出div+css格式HTML(自动)

    psd切片切好后,导出 web格式,存储时选择html.所有切片,然后,选择其他,选择自定,选择切片,选择生成css css命名有2种方式,根据ID和根据类,一般选择根据类(ID尽量少有,防止js要用 ...

  9. JS模式:jq中简单的模式--》采摘自js设计(tomxu_version)

    <!DOCTYPE html> <html> <head> <title></title> </head> <body&g ...

  10. Java编程思想学习(十三) java I/O

    Java中使用流来处理程序的输入和输出操作,流是一个抽象的概念,封装了程序数据于输入输出设备交换的底层细节.JavaIO中又将流分为字节流和字符流,字节流主要用于处理诸如图像,音频视频等二进制格式数据 ...