ACM解题之(ZOJ 2212) Argus

题目来源:

点击打开题目

题目翻译:

数据流是实时的,连续的,有序的项目序列。一些例子包括传感器数据,互联网流量,金融代码,在线拍卖以及诸如网络使用日志和电话记录之类的交易日志。同样,对流进行的查询在一段时间内连续运行,并在新数据到达时递增返回新结果。例如,工厂仓库的温度检测系统可以运行如下的查询。

查询-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;
}

转载于:https://www.cnblogs.com/surecheun/p/9648978.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值