百练2051题目(python解法)

目录

1.题目

2.开始吹水

1.堆是什么

2.堆的分类

3.堆属性

3.回到题目(不想看吹水的可以先看这里)


1.题目

描述

数据流是一个实时的、连续的、有序的项目序列。一些示例包括传感器数据、Internet流量、金融报价、在线拍卖和事务日志(如Web使用日志和电话记录)。同样,流上的查询在一段时间内连续运行,并在新数据到达时递增地返回新结果。例如,工厂仓库的温度检测系统可能运行如下查询。
查询-1:“每隔五分钟,检索过去五分钟内的最高温度。”
查询-2:“返回过去10分钟内每层楼的平均温度。”

我们开发了一个名为Argus的数据流管理系统,它可以处理数据流上的查询。用户可以向Argus注册查询。Argus将在不断变化的数据上保持查询运行,并以期望的频率将结果返回给相应的用户。

对于Argus,我们使用以下指令注册查询:
Register     Q_num      Period

Q_num (0 < Q_num <= 3000)为查询的ID-number, Period (0 < Period <= 3000)为查询结果连续两次返回的时间间隔。在注册周期秒后,第一次返回结果,之后每周期秒返回一次结果。

这里我们一次在Argus中注册了几个不同的查询。确认所有查询都有不同的Q_num。您的任务是告诉前K个查询返回结果。如果两个或多个查询要同时返回结果,它们将按照Q_num的升序依次返回结果。


输入

输入的第一部分是给Argus的寄存器指令,每行一个指令。您可以假设指令的数量不会超过1000条,并且所有这些指令都是同时执行的。这部分以一行“#”结束。

第二部分是你的任务。这部分只包含一行,是一个正整数K(<= 10000)。


输出


您应该输出前K个查询的Q_num以返回结果,每行一个数字。

样例输入

Register 2004 200
Register 2005 300
#
5

样例输出

2004
2005
2004
2004
2005

我们先根据样例输入和输出来读题,样例输入两个查询号,2004和2005。其中2004的查询时间是200s(权当1周期秒是1秒),2005查询时间是300s。输出先经过200秒输出2004,再过100秒输出2005,再过100秒,这时离第一次输出2004已经过了200秒,输出2004。再过200秒,这个时候2004和2005应当同时输出,所以按照升序排列输出,先输出2004,再输出2005.

题目说输出前5个任务,即输出

2004 2005 2004 2004 2005

下面画一幅图帮助理解

好,我们现在来观察样例输出,是不是很像下面这张图片

 嗯,这个就是数据结构里的堆

2.开始吹水

1.堆是什么

堆(heap):一种有特殊用途的数据结构——用来在一组变化频繁(发生增删查改的频率较高)的数据集中查找最值。

堆在逻辑结构上,一般被视为是一颗完全二叉树。

2.堆的分类

堆分为最大堆和最小堆,在最大堆中,父节点总是比子节点大,而最小堆相反。

3.堆属性

设i为数组下标

如果 i 为0,则 i 表示的节点为根节点,否则i节点的双亲节点为 (i - 1)/2;

如果2 * i + 1 小于节点个数,则节点i的左孩子下标为2 * i + 1,否则没有左孩子;

如果2 * i + 2 小于节点个数,则节点i的右孩子下标为2 * i + 2,否则没有右孩子。


因为这道题需要按照时间顺序输出最先到达时间点的K个查询,而且如果多个查询在同一时间到达,则需要按照查询ID升序输出。依照题意,我们需要用到最小堆来存储数据。

而python中刚好有一个名为heapq的最小堆的库,我们的问题刚刚好就要用到这个库。

3.回到题目(不想看吹水的可以先看这里)

这道题需要按照时间顺序输出最先到达时间点的K个查询,所以我们利用heappush()方法创建一个最小堆并把需要查询的ID和对应的周期秒放入堆中。

heapq.heappush(heap, item) 是一个 Python 内置函数,用于将元素 item 加入到 heap 中。其中 heap 是一个列表,它表示一个堆。这个方法会将元素 item 加入到堆中,并按照堆的规则调整堆,使得堆的根节点(即最小元素)在堆顶,保证堆是有序的。

这样最先查询到的数字就被放在最前面了,现在就差输出了,方法是heappop()

heapq.heappop(heap) 是 Python 的一个堆操作方法,用于从堆中弹出最小的元素并返回该元素。

下面是完整的代码

import heapq

# 定义一个堆来存储各个任务
heap = []

# 读入每个任务的信息,按照周期将任务加入堆中
while True:
    s = input().strip()
    if s == "#":
        break
    # _ 表示无用的返回值,这里用 _ 来忽略第一个数(就是那个Register)
    _, q_num, period = s.split()
    heapq.heappush(heap, (int(period), int(q_num), int(period)))

# 读入需要查询的次数
k = int(input())

# 对于每次查询,从堆中取出下一个周期最小的任务,并输出其任务编号
for _ in range(k):
    period, q_num, init_period = heapq.heappop(heap)
    print(q_num)
    # 将该任务的下一次周期加入堆中
    heapq.heappush(heap, (period+init_period, q_num, init_period))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值