• 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/
  • 相关阅读:
    php json_encode JSON_UNESCAPED_UNICODE
    ubuntu 添加多个ssh公钥和私钥
    如何自动化新增配置文件呢?
    git配置ssh公钥
    项目PHP新知识点
    mysql 数据库复制表 create table city1 like city;
    .NET 泛型集合数据写CSV文件
    .NET C# 泛型队列
    逆向地理编码--根据地址搜索定位,点击地图、获取经纬度信息
    正向地理编码-根据输入地址获取经纬度
  • 原文地址:https://www.cnblogs.com/surecheun/p/9648978.html
Copyright © 2020-2023  润新知