参考y神的思路QWQ
算法:贪心
对于每一个任务:
- (y) 的差异最多能使利润(w)浮动(2 * 100 = 200)元。
- (x) 差(1),则会使利润(w)浮动(500)元
所以,(y)对利润的影响较小,(x)与其利润(w)的关系成对应关系(即(x_{i} < x_{j}),则(w_{i}<w_{j}),仅当(x_{i} = x_{j}),再按照(y)考虑即可。
策略可以变成以(x)从大到小的顺序考虑每一个任务,如果能匹配机器,则从能匹配的机器中选择机器(y)最小的一个。
匹配机器
- 先用(x)分别从大到小排序任务与机器。
- 对于每一个任务,把时间充足的机器放入集合中。
- 若存在,从集合中找出级别最低的机器使用,并且从集合中删除那个机器。
这种处理顺序可以保证:在处理第下一个任务时,集合中的机器时间都是充足的。且找机器的时间复杂度处于(O(M+N))级别。
(STL) 的 (multiset) 恰好支持从序列中查找大于等于某数的最小值。
时间复杂度:O(MlogN + N)
(multiset) 的 (lowerbound) 时间为(O(logN))的...
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<set>
using namespace std;
typedef pair<int,int> PII;
const int N = 100000 + 10;
int n, m;
PII a[N],b[N];
int main(){
while(cin >> n >> m){
for(int i = 1; i <= n; i++) cin >> a[i].first >> a[i].second;
for(int i = 1; i <= m; i++) cin >> b[i].first >> b[i].second;
sort(a + 1,a + 1 + n); sort(b + 1,b + 1 + m);
multiset<int> s; s.clear();
long long cnt = 0, ans = 0;
for(int i = m, j = n; i >= 1; i--){
//将时间足够的机器放到set中
while(j >= 1 && b[i].first <= a[j].first)s.insert(a[j--].second);
multiset<int>::iterator it = s.lower_bound(b[i].second);
if(it != s.end()){
cnt ++;
ans += 500 * b[i].first + 2 * b[i].second;
s.erase(it);
}
}
cout << cnt << " " << ans << endl;
}
return 0;
}