NC16430 [NOIP2016]蚯蚓
NC16430 [NOIP2016]蚯蚓
题目
题目描述
本题中,我们将用符号 \(\lfloor c \rfloor\) 表示对 c 向下取整,例如:\(\lfloor 3.0 \rfloor = \lfloor 3.1 \rfloor = \lfloor 3.9 \rfloor = 3\) 。
蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓。
蛐蛐国里现在共有 n 只蚯蚓(n 为正整数)。每只蚯蚓拥有长度,我们设第 i 只蚯蚓的长度为 \(a_i (i = 1, 2, \ldots , n)\),并保证所有的长度都是非负整数(即:可能存在长度为 0 的蚯蚓)。
每一秒,神刀手会在所有的蚯蚓中,准确地找到最长的那一只(如有多个则任选一个)将其切成两半。神刀手切开蚯蚓的位置由常数 p(是满足 0 < p < 1 的有理数)决定,设这只蚯蚓长度为 x,神刀手会将其切成两只长度分别为 \(\lfloor px \rfloor\) 和 \(x - \lfloor px \rfloor\) 的蚯蚓。特殊地,如果这两个数的其中一个等于 0,则这个长度为 0 的蚯蚓也会被保留。此外,除了刚刚产生的两只新蚯蚓,其余蚯蚓的长度都会增加 q(是一个非负整常数)。
蛐蛐国王知道这样不是长久之计,因为蚯蚓不仅会越来越多,还会越来越长。蛐蛐国王决定求助于一位有着洪荒之力的神秘人物,但是救兵还需要 m 秒才能到来 ……(m 为非负整数)
蛐蛐国王希望知道这 m 秒内的战况。具体来说,他希望知道:
·m 秒内,每一秒被切断的蚯蚓被切断前的长度(有 m 个数);
·m 秒后,所有蚯蚓的长度(有 n + m 个数)。
蛐蛐国王当然知道怎么做啦!但是他想考考你 ……
输入描述
第一行包含六个整数 n,m,q,u,v,t,其中:n,m,q 的意义见「题目描述」;u,v,t 均为正整数,你需要自己计算 \(p = \frac{u}{v}\)(保证 0 < u < v);t 是输出参数,其含义将会在「输出描述」中解释。
第二行包含 n 个非负整数,为 a1, a2, ..., an,即初始时 n 只蚯蚓的长度。
同一行中相邻的两个数之间,恰好用一个空格隔开。
保证 \(1 ≤ n ≤ 10^5,0 < m < 7 x 10^6,0 < u < v < 10^9,0 ≤ q ≤ 200,1 < t < 71,0 < a_i < 10^8\)。
输出描述
第一行输出 \(\lfloor \frac{m}{t} \rfloor\) 个整数,按时间顺序,依次输出第 t 秒,第 2t 秒,第 3t 秒 …… 被切断蚯蚓(在被切断前)的长度。
第二行输出 \(\lfloor \frac{(n+m)}{t} \rfloor\)个整数,输出 m 秒后蚯蚓的长度;需要按从大到小的顺序,依次输出排名第 t,第 2t,第 3t …… 的长度。
同一行中相邻的两个数之间,恰好用一个空格隔开。即使某一行没有任何数需要输出,你也应输出一个空行。
请阅读样例来更好地理解这个格式。
示例1
输入
3 7 1 1 3 1
3 3 2
输出
3 4 4 4 5 5 6
6 6 6 5 5 4 4 3 2 2
说明
在神刀手到来前:3 只蚯蚓的长度为 3, 3, 2。
1 秒后:一只长度为 3 的蚯蚓被切成了两只长度分别为 1 和 2 的蚯蚓,其余蚯蚓的长度增加了 1。最终 4 只蚯蚓的长度分别为 (1, 2), 4, 3。括号表示这个位置刚刚有一只蚯蚓被切断;
2 秒后:一只长度为 4 的蚯蚓被切成了 1 和 3。5 只蚯蚓的长度分别为:2, 3, (1, 3), 4;
3 秒后:一只长度为 4 的蚯蚓被切断。6 只蚯蚓的长度分别为:3, 4, 2, 4, (1, 3);
4 秒后:一只长度为 4 的蚯蚓被切断。7 只蚯蚓的长度分别为:4, (1, 3), 3, 5, 2, 4;
5 秒后:一只长度为 5 的蚯蚓被切断。8 只蚯蚓的长度分别为:5, 2, 4, 4, (1, 4), 3, 5;
6 秒后:一只长度为 5 的蚯蚓被切断。9 只蚯蚓的长度分别为:(1, 4), 3, 5, 5, 2, 5, 4, 6;
7 秒后:一只长度为 6 的蚯蚓被切断。10 只蚯蚓的长度分别为:2, 5, 4, 6, 6, 3, 6, 5, (2, 4)。所以,7 秒内被切断的蚯蚓的长度依次为 3, 4, 4, 4, 5, 5, 6。7 秒后,所有蚯蚓长度从大到小排序为 6, 6, 6, 5, 5, 4, 4, 3, 2, 2。
示例2
输入
3 7 1 1 3 2
3 3 2
输出
4 4 5
6 5 4 3 2
说明
这个数据中只有 t = 2 与上个数据不同。只需在每行都改为每两个数输出一个数即可。
虽然第一行最后有一个 6 没有被输出,但是第二行仍然要重新从第二个数再开始输出。
备注
\(1 ≤ n ≤ 10^5, 0 ≤ m ≤ 7 \times 10^6, 1 ≤ t ≤ 71, 0 ≤ a_i ≤ 10^8, 1 ≤ v ≤ 10^9, 0 ≤ q ≤ 200\)
题解
思路
知识点:队列。
这道题用优先队列会被卡,而用队列即可维护单调性,不需要优先队列。
首先按从大到小排序,设置一个队列存放原来的蚯蚓,两个队列分别存放分割的两部分。由于分割比例相同,而蚯蚓是从大到小选的,则分割的两部分一定能各自递减排列,只需要分别放入两个新队列的队尾即可。
每次三个队列队头找最大值,为了方便标记,一开始用队列数组创建三个队列,先从三个队列中找到任意一个非空队列标记上,然后再在三个队列中找到非空队列的队头最大值并标记,随后就得到了最大的队头所在队列的下标。
因为每次所有蚯蚓,除了这次分割的蚯蚓,都长度增加 \(q\) ,一个一个加显然不合理,注意到 \(q\) 和时间有关,那么如果当前时间是第 \(i\) 秒蚯蚓原长是 \(len\),假设蚯蚓没有切割过,那么长度就为 \(len + (i-1)q\) ,\(i-1\) 是因为第 \(i\) 秒只长了 \(i-1\) 秒,第 \(i\) 秒后才是 \(i\) 。
现在考虑分割的蚯蚓如何计算,因为分割需要用真实长度,因此必须先计算出真实长度 \(x\) ,然后计算出新蚯蚓长度 $l = \lfloor x\cdot \frac{u}{v} \rfloor $ ,\(r = l - x\) ,前者可以不用浮点运算,先计算 \(xu\) 再整除 \(v\) ,记得开 \(long \ long\) ,如此得到新蚯蚓的真实长度。但是,真实长度是不兼容我们对新增长度的优化的,因为如此新蚯蚓的增长时间就不一样了,有两种方案:第一种,记录新蚯蚓产生时间是第 \(k\) 秒,那么第 \(i\) 秒长度就为 \(len + (i-1-k)q\) ,并非 \(k-1\) 因为新切的蚯蚓在第 \(k\) 秒后也是不会增长的,因此实际增长时间要从第 \(k+1\) 秒开始计算到之前第 \(i\) 秒,一共 \(i - k - 1\) 秒;第二种,计算新蚯蚓的假想初始长度,即假设新蚯蚓一开始就存在,求出在第 \(i\) 秒后(因为第 \(i\) 秒之前切完到第 \(i\) 秒后长度不变)增长到这个长度的初始长度,这样就能兼容一开始用当前时间计算长度的方式了,那么假想初始长度就是 \(len - i\cdot q\) ,因为增长了 \(i\) 秒一共 \(i\cdot q\) 的长度。最后把长度分别放入两个新队列里。
因为不是每秒都输出,用一个计数器 \(tcnt\),记录下一次输出的时间是 \(t\) 的几倍,\(i == tcnt \cdot t\) 时输出第 \(tcnt \cdot t\) 秒的切割蚯蚓的长度。
最后不用 \(sort\) 排序,因为三队列都是有序的,直接归并即可,输出方式同上。
时间复杂度 \(O(n \log n +m)\)
空间复杂度 \(O(n)\)
代码
#include <bits/stdc++.h>
using namespace std;
int a[100007];
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, m, q, u, v, t;
cin >> n >> m >> q >> u >> v >> t;
for (int i = 0;i < n;i++) cin >> a[i];
sort(a, a + n, [&](int a, int b) {return a > b;});
queue<int> Q[3];
for (int i = 0;i < n;i++) Q[0].push(a[i]);
int tcnt = 1;///计时器
for (int i = 1;i <= m;i++) {///用最初长度加增长长度代表真实长度
int pos = 0;
///找到最大的蚯蚓
for (int j = 0;j < 3;j++)
if (!Q[j].empty()) pos = j;
for (int j = 0;j < 3;j++)
if (!Q[j].empty() && Q[pos].front() < Q[j].front()) pos = j;
int x = Q[pos].front() + (i - 1) * q;///第i秒的真实长度
if (i == tcnt * t)cout << x << ' ', tcnt++;
Q[pos].pop();
int l = 1LL * x * u / v;///分割后的真实长度
int r = x - l;
///分割的假设最初长度,计算增长长度公式就能统一了
Q[1].push(l - i * q);///第i秒后长度为l,因此初始长度是 l - i*q
Q[2].push(r - i * q);///同上
}
cout << '\n';
tcnt = 1;
for (int i = 1;i <= n + m;i++) {///三路归并
int pos = 0;
for (int j = 0;j < 3;j++)
if (!Q[j].empty()) pos = j;
for (int j = 0;j < 3;j++)
if (!Q[j].empty() && Q[pos].front() < Q[j].front()) pos = j;
if (i == tcnt * t) cout << Q[pos].front() + m * q << ' ', tcnt++;
Q[pos].pop();
}
return 0;
}
NC16430 [NOIP2016]蚯蚓的更多相关文章
- [Noip2016]蚯蚓 D2 T2 队列
[Noip2016]蚯蚓 D2 T2 Description 本题中,我们将用符号[c]表示对c向下取整,例如:[3.0」= [3.1」=[3.9」=3.蛐蛐国最近蚯蚓成灾了!隔壁跳 蚤国的跳蚤也拿蚯 ...
- 【BZOJ】4721: [Noip2016]蚯蚓 / 【洛谷】P2827 蚯蚓(单调队列)
Description 本题中,我们将用符号[c]表示对c向下取整,例如:[3.0」= [3.1」=[3.9」=3.蛐蛐国最近蚯蚓成灾了!隔壁跳 蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮 ...
- 【bzoj4721】[Noip2016]蚯蚓
题目描述 本题中,我们将用符号[c]表示对c向下取整,例如:[3.0」= [3.1」=[3.9」=3.蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓.蛐 ...
- 【uoj264】 NOIP2016—蚯蚓
http://uoj.ac/problem/264 (题目链接) 题意 n条蚯蚓,时间为m.每单位时间要可以将最长的蚯蚓切成len/2和len-len/2两份,长度为0的蚯蚓不会消失,因为每单位时间所 ...
- BZOJ4721 [Noip2016]蚯蚓
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...
- [NOIp2016] 蚯蚓
类型:单调队列 传送门:>Here< 题意:有$N$只蚯蚓,每秒都会伸长$q$.每一次都会有人选出最长的一条切成两半,长度分别是$\left \lfloor px \right \rflo ...
- luogu2827 [NOIp2016]蚯蚓 (模拟)
可以直观地想到用优先队列来做,但数据范围是O(n)的 然后我们发现,因为我们每次挑出来的蚯蚓是单调的,所以把每个切成两段后,那两段也是对应单调的 也就是说,算上最一开始的蚯蚓,我们一共维护三个队列,三 ...
- [NOIp2016]蚯蚓 (队列)
#\(\color{red}{\mathcal{Description}}\) LInk 这道题是个\(zz\)题 #\(\color{red}{\mathcal{Solution}}\) 我们考虑如 ...
- 【bzoj4721】[Noip2016]蚯蚓 乱搞
题目描述 本题中,我们将用符号[c]表示对c向下取整,例如:[3.0」= [3.1」=[3.9」=3.蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓.蛐 ...
随机推荐
- 2021.10.29 数位dp
2021.10.29 数位dp 1.数字计数 我们先设数字为ABCD 看A000,如果我们要求出它所有数位之和,我们会怎么求? 鉴于我们其实已经求出了0到9,0到99,0到999...上所有数字个数( ...
- Spring 源码(3)Spring BeanFactory 是怎么创建的?
Spring创建 BeanFactory 的方式 按照Bean的配置方式手动创建可以分为两种: 使用XMl配置的Bean 这种方式使用xml配置文件配置Bean的信息并且设置扫描的路径,扫描到的包可以 ...
- 解决go-micro与其它gRPC框架之间的通信问题
在之前的文章中分别介绍了使用gRPC官方插件和go-micro插件开发gRPC应用程序的方式,都能正常走通.不过当两者混合使用的时候,互相访问就成了问题.比如使用go-micro插件生成的gRPC客户 ...
- python基础-基本数据类型(二)
一.序列类型 序列类型是用来表示有序的元素集合 1.字符串(str) python中字符串通常用str表示,字符串是使用单引号,双引号,三引号包裹起来的字符的序列,用来表示文本信息. 1.1 字符串的 ...
- zookeeper篇-初识zookeeper
点赞再看,养成习惯,微信搜索「小大白日志」关注这个搬砖人. 文章不定期同步公众号,还有各种一线大厂面试原题.我的学习系列笔记. 什么是zookeeper? 中间件 作用于分布式系统 支持java.c语 ...
- 灵感乍现!造了个与众不同的Dubbo注册中心扩展轮子
hello大家好呀,我是小楼. 作为一名基础组件开发,服务好每一位业务开发同学是我们的义务(KPI). 客服群里经常有业务开发同学丢来一段代码.一个报错,而我们,当然要微笑服务,耐心解答. 有的问题, ...
- 详解Fiddler Classic过滤、重放、转发HTTP请求
更多干货文章,更多最新文章,欢迎到作者主博客 菜鸟厚非 一.简介 今天介绍一下 Fiddler Classic 对 HTPP 的过滤.重放.转发操作,这在开发中,尤其在微服务中调试中是经常用到的功能, ...
- mybaitis查询 (数据库与实体类字段名不相同)
1.这是我的数据库字段名和实体类字段名 2.方法 方法一: 查询的结果标题 会跟实体类的属性一一匹配,一定要一致就算数据库字段和属性不一致,我们可以把查询结果设置一个别名,让别名=属性名 方法二:使用 ...
- HCNP Routing&Switching之MSTP
前文我们了解了RSTP保护相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/16255918.html:今天我们来了解下MSTP相关话题: MSTP技术背 ...
- Nacos源码系列—订阅机制的前因后果(上)
点赞再看,养成习惯,微信搜索[牧小农]关注我获取更多资讯,风里雨里,小农等你,很高兴能够成为你的朋友. 项目源码地址:公众号回复 nacos,即可免费获取源码 前因 我们在了解Nacos订阅机制之前, ...