在試圖提高我的算術技巧時,我發現自己陷入了下面的問題,總之,要求您找出房間中存在最多人數的時間段的持續時間:重疊事件的最大次數
https://jutge.org/problems/P27158_en
的解決方案,我想出瞭解決問題的正確所有的網站建議的公開測試的情況下,但它失敗的一個或多個隱藏私人測試用例。
我的解決方案爲std :: vector中的每個事件保存兩個條目:一個用於到達,另一個用於離開,每個由[eventtype,eventtime]組成。然後通過事件時間對矢量進行排序,最後循環遍歷矢量以確定具有最大數量的客人的時間段的持續時間。我的代碼如下:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
enum class EventType {ARRIVE, LEAVE};
struct Event{
int time;
EventType type;
Event(){}
Event(int tm, EventType t) : time(tm), type (t){}
// inline bool operator<(const Event& e) const {return time < e.time || (time == e.time && type==EventType::LEAVE);}
};
bool eventCompare(const Event& e1, const Event& e2) {
if(e1.time < e2.time){
return true;
} else if(e1.time == e2.time) {
if(e1.type == EventType::LEAVE && e2.type == EventType::ARRIVE) {
return true;
} else {
return false;
}
} else {
return false;
}
}
int main()
{
int visits;
int timeStart, timeEnd;
int maxVisits, maxDuration, localMaxVisits, localStartTime, localEndTime, duration;
std::vector<Event> events;
std::vector<Event>::const_iterator it;
// Get each Case from stdin.
// 0 is the special stopping case.
while(cin>>visits && visits!=0) {
events.clear();
// Read all the visits, for each one save two entries to the visits-vector,
// one for the arrival time another for the leaving time.
for(int i=1; i<=visits; ++i){
cin>>timeStart>>timeEnd;
Event eStart(timeStart, EventType::ARRIVE);
Event eEnd(timeEnd, EventType::LEAVE);
events.push_back(eStart);
events.push_back(eEnd);
}
// Sorting the vector so that events are ordered by their arrival time.
// In case two events coincide on arrival time, we place leaving events before arrival events.
std::sort(events.begin(), events.end(), eventCompare);
maxVisits=0;
maxDuration=0;
localMaxVisits=0;
localStartTime=0;
localEndTime=0;
// Loop through the sorted vector
for(it=events.begin(); it!=events.end(); ++it){
// If the event type is arrival
if((*it).type == EventType::ARRIVE) {
// We only reset the localStartTime if there is no
// gap between the last endtime and the current start time
// For example two events 11-13 and 13-15 should be treated as one long event
// with duration 11-15
if(localEndTime < (*it).time) {
localStartTime = (*it).time;
}
localMaxVisits++;
} else { // Event type leave
// Calculate the duration
duration = (*it).time - localStartTime;
// If we have a new max in overlaps or equal overlaps but larger duration than previous
// We save as the global max.
if(localMaxVisits > maxVisits || (localMaxVisits == maxVisits && duration>maxDuration)) {
maxVisits=localMaxVisits;
maxDuration = duration;
}
localMaxVisits--;
localEndTime= (*it).time;
}
}
cout<<maxVisits<<" "<<maxDuration<<endl;
}
return 0;
}
我從@j_random_hacker相應地修改代碼註釋和程序現在,因爲它的隱藏私人測試用例以前那樣不超過時間限制,但現在得到一個判決「錯誤的答案」(僅適用於私人測試用例)。我會試着找出算法錯誤可能是什麼。感謝所有回答的人。
該算法看起來不錯。你有沒有簡要介紹一下這麼久?它是std :: sort()還是別的?還是你編譯它沒有編譯器優化,他們將運行時間限制與優化程序對齊? – Heinzi
我還沒有嘗試描述執行情況,但搜索文檔時我總結說std :: sort應該是排序向量的最快方法。換句話說,即使我發現std :: sort在大數據集中需要相對較長的時間,我也不知道應該使用哪種排序算法。但是你是對的,我應該檢查至少部分代碼是主要的時間消費者。至於你的其他問題,我只提交源代碼到測試網站,所以我不知道他們編譯了哪些編譯器設置,然後執行我的程序。 – AsbjornF
我認爲'排序'不應該是你應該加快你的算法的第一個地方。相反,我相信你的循環內容對於算法的速度更重要。然而,正如Heinzi所指出的那樣,分析技術在確定算法瓶頸方面肯定會有所幫助。 – Nard