题目来源:
题目翻译:
数据流是实时的,连续的,有序的项目序列。一些例子包括传感器数据,互联网流量,金融代码,在线拍卖以及诸如网络使用日志和电话记录之类的交易日志。同样,对流进行的查询在一段时间内连续运行,并在新数据到达时递增返回新结果。例如,工厂仓库的温度检测系统可以运行如下的查询。
查询-1: 每五分钟,检索过去五分钟内的最高温度
查询-2: 返回过去10分钟内每层测得的平均温度
我们开发了一个名为Argus的数据流管理系统,它处理数据流上的查询。用户可以向Argus注册查询。 Argus将保持查询在不断变化的数据上运行,并将结果以所需的频率返回给相应的用户。
对于Argus,我们使用以下指令来注册查询: 注册 Q_num 周期
Q_num(0 <Q_num <= 3000)是查询ID号码,而周期(0 <期间<= 3000)是结果的两个连续返回之间的间隔。在注册周期的第几秒后,结果将首次返回,之后,结果将每隔一个周期返回一次。 这里我们有几个不同的查询在Argus一次注册。保证所有的查询都有不同的Q_num。你的任务是输出前K个查询结果。如果两个或多个查询要同时返回结果,它们将按Q_num的升序顺序返回结果。
输入:输入的第一部分是对Argus的注册指令,每行一条指令。您可以假设指令的数量不会超过1000,并且所有这些指令都是同时执行的。这部分以一行 # 结束。 第二部分是你要输出的结果数。该部分只包含一行,即一个正整数K(<= 10000)。
输出:您应输出前K个查询的Q_num的返回结果,每行一个数字。
Sample Input
Register 2004 200
Register 2005 300
#
5
SampleOutput
2004
2005
2004
2004
2005
这道题的意思时,注册一个查询的时候给定这个查询一个周期,然后实现周期性查找。例如输入‘Register 2004 200’,则每隔200个单位时间,就会重复执行ID为2004的查询(这里即输出2004);输入‘Register 2005 300’,则每隔300秒就会执行ID为2005的查询(这里即输出2005)。所以同时输入上述两个命令,就会得到2004(200s时),2005(300s时),2004(400s时),2004(600s时),2005(600时后)。。。600s时会先输出2004,因为题目说了同时输出时,会按ID号的升序输出!
这个题目和我上一篇的windows消息处理的题目很类似,都是要比较两个指标的大小,当主指标一样时,比较次指标,而且这两个题都规定了次指标一定不一样!所以,这道题我还是用了优先队列来做。
首先定义一个任务结构,每个任务对象包括三个整形数,一个表示ID号,一个表示周期,一个表示当前时间时间。然后写一个重载<函数,定义任务点的大小比较规则:符合输出的当前时间一样时,比较ID号;符合输出的当且时间不一样时,比较当前时间。
具体看代码:
/*
c++/accepted
*/
#include<iostream>
#include<queue>
#include<string>
using namespace std;
struct node { //定义任务点结构
int p, t, p_num;
bool friend operator < (node a, node b) {
if (a.t == b.t)
return a.p_num > b.p_num; //如果当前输出时间一样,则比较ID号
return a.t > b.t; //否则直接比较当前输出时间
}
}an;
int main() {
string ss;
priority_queue<node> q; //申请一个node的优先队列
int k;
cin >> ss; //输入Register或#
while (ss!="#") { //如果输入的ss不为'#",则继续输入
cin >> an.p_num; //输入ID号
cin >> an.p; //输入周期
an.t = an.p; //把当前输出时间初始化为周期,因为一个周期后才输出
q.push(an); //把任务点push进队列
cin >> ss; //输入Register或#
}
cin >> k; //输入k
while(k--)
{
an = q.top(); //取出队列头对象
cout << an.p_num << endl; //输出当前任务的ID
an.t = an.t + an.p; //更新当前任务的输出时间为原时间加上该任务的周期,因为此任务的下次输出要等一个周期
q.pop(); //让第一个对象出队
q.push(an); //把更新了的任务进队
} //直到输出够k个
return 0;
}