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.08.01 P4359 伪光滑数(二叉堆)
2021.08.01 P4359 伪光滑数(二叉堆) [P4359 CQOI2016]伪光滑数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 若一个大于 11 的整数 MM ...
- k8s入门之基础环境准备(一)
一.在虚拟机中安装Ubuntu20.04.4系统 1.下载Ubuntu20.04.4服务器版本系统 下载链接地址如下: https://mirrors.tuna.tsinghua.edu.cn/ubu ...
- Windows下查找各类游戏存档路径
我算是个比较爱打单机游戏的人,同时也是个半吊子的编程爱好者,有的时候会去干一些修改存档的事儿.不过这篇博文不讲存档修改技术,只讲第一步:去哪找存档? 目标:在windows10系统下搜索到游戏的存档路 ...
- java基础4.20
1.是否可以从一个static方法内部发出对非static方法的调用? 不可以.因为非static方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而static方法调用时 ...
- 一文读懂 Kubernetes 容器网络
点击上方"开源Linux",选择"设为星标" 回复"学习"获取独家整理的学习资料! 在Kubernetes中要保证容器之间网络互通,网络至关 ...
- 实战| Nginx+keepalived 实现高可用集群
一个执着于技术的公众号 前言 今天通过两个实战案例,带大家理解Nginx+keepalived 如何实现高可用集群,在学习新知识之前您可以选择性复习之前的知识点: 给小白的 Nginx 10分钟入门指 ...
- 简单易懂的 Go 泛型使用和实现原理介绍
原文:A gentle introduction to generics in Go by Dominik Braun 万俊峰Kevin:我看了觉得文章非常简单易懂,就征求了作者同意,翻译出来给大家分 ...
- 【Azure 环境】【Azure Developer】使用Python代码获取Azure 中的资源的Metrics定义及数据
问题描述 使用Python SDK来获取Azure上的各种资源的Metrics的名称以及Metrics Data的示例 问题解答 通过 azure-monitor-query ,可以创建一个 metr ...
- SyntaxError: Non-UTF-8 code starting with '\xef' in file(已解决)
错误原因: python代码中出现了中文字符 解决方案: 在python代码文件的第一行(必须是第一行)添加如下代码(随编码不同自行修改): #coding=utf-8
- 每天一个 HTTP 状态码 206
206 Partial Content 206 Partial Content 是当客户端请求时使用了 Range 头部,服务器端回复的响应,表示只响应一部分内容. 实例 请求: GET /favor ...