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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章