【51NOD—貪心演算法專題】 E 做任務三 區間貪心+不相交子區間最少人數
阿新 • • 發佈:2019-01-30
基準時間限制:1 秒 空間限制:131072 KB 分值: 5 B君和m個人一起,要完成n個任務,在這個題中,B君和m個人,什麼都不做。 第i個任務有一個開始時間s[i]和結束時間e[i](保證s[i]<=e[i]),一個人完成兩個任務的時間區間, 不能有交集,但是可以首尾相連。(參考樣例) 換句話說,如果一個人依次完成了(s[1], e[1]) (s[2], e[2]) (s[3], e[3])這3個任務, 那麼這3個任務需要滿足s[1]<=e[1]<=s[2]<=e[2]<=s[3]<=e[3]。 同一個任務只能完成一次,並且中間不能換人。 B君和m個人,想知道要想完成這些任務,至少需要幾個人? (單組 n <= 100000) (所有 n 求和 <= 200000) (開始時間和結束時間,都是非負整數,且在int範圍內。) (開始時間 <= 結束時間,如果等於的話,意味著這個任務可以瞬間被做完,但是不能沒有人做)
Input
多組資料,第一行是資料組數。
每組資料的第一行兩個整數n, m分別表示任務數,和人數。
以下n行,每行兩個整數表示任務的開始時間和結束時間。
Output
對於每組資料輸出一個整數
表示完成這些任務至少需要多少人。
Input示例
4
2 1
1 3
2 4
2 1
1 3
3 5
2 1
1 3
2 2
4 1
1 2
2 2
2 2
2 3
Output示例
2
1
2
1
思路1
#include <iostream> #include <cstdio> #include <algorithm> #include <queue> using namespace std; const int nmax=200000+10; pair<int,int>a[nmax]; int main(int argc, char** argv) { int t; while(cin>>t){ while(t--){ priority_queue<int>q; int n;//任務數 int m;//人數 cin>>n>>m; for(int i=0;i<n;i++){ cin>>a[i].first>>a[i].second; } sort(a,a+n);//按照first排序 //加入相反數實現小根堆的效果,就是根是絕對值越小的 int z=0; for(int i=0;i<n;i++){ //遇到一個新任務,試圖讓q.top()去接 //如果能接,則更新 if(q.size()>0&&-q.top()<=a[i].first){ q.pop();//彈出q.top(); q.push(-a[i].second); } //如果不能接,則新開一個人去接 else{ q.push(-a[i].second); z++; } } cout<<z<<endl; } } return 0; }
————————————————————————————————————————————————————————
思路2
#include <iostream> #include <set> #include <cstdio> #include <algorithm> using namespace std; const int nmax=200000+20; pair<int,int>a[nmax]; int main(int argc, char** argv) { int t; while(cin>>t){ while(t--){ int n; int m; cin>>n>>m; for(int i=0;i<n;i++){ cin>>a[i].second>>a[i].first; } sort(a,a+n);//按照first排序 multiset<int>s;//維護所有人的結束時間 int z=0; //如果能接(小於等於開始時間)的最晚的人 //upper_bound找到大於等於最早的 //--upper_bound 就是小於等於最晚的 for(int i=0;i<n;i++){ if(s.size()>0&& *s.begin()<=a[i].second){ s.erase(--s.upper_bound(a[i].second)); //--s.upper_bound(a[i].second); s.insert(a[i].first); } //如果接不了此任務,新開一個人 else{ s.insert(a[i].first); z++; } } //cout<<z<<endl; printf("%d\n",z); } } return 0; }