題目來源:
題目翻譯:
數據流是實時的,連續的,有序的項目序列。一些例子包括傳感器數據,互聯網流量,金融代碼,在線拍賣以及諸如網絡使用日誌和電話記錄之類的交易日誌。同樣,對流進行的查詢在一段時間內連續運行,並在新數據到達時遞增返回新結果。例如,工廠倉庫的溫度檢測系統可以運行如下的查詢。
查詢-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;
}