版权声明:欢迎转载,不要求署名~~~ https://blog.csdn.net/shadandeajian/article/details/82353386
传送门:题目
题意:
先给n对数据,每对代表一门考试,每对的第一个数字代表考试的日子,第二个数字代表需要复习的天数。然后再给m对数字,代表区间[l,r]内既不能复习,也不能参加考试。问学生最多能获得几门学科的学分。
题解:
很明显的贪心题目,千万不要以复习天数的多少贪心,因为这样会忽略掉考试的时间和非法区间的存在。我的想法是把每门课程看作一个区间,然后把这个区间和非法区间一起合并进一个vector里去,然后排个序,我们基于考试的时间和非法区间的l进行贪心。然后非法区间无非就是看作课程多复习一段时间。然后再判断能不能完成这门课程就行了。
最后说一点,pair套emplace_back真的好简洁。
AC代码:
#include <bits/stdc++.h>
#define debug(x) cout<<#x<<" = "<<x<<endl;
using namespace std;
#define PLL pair<long long,long long>
const int maxn = 1e5 + 10;
vector<int> res;
vector<PLL> p, f;
long long n, m, exam_day[maxn], review_day[maxn];//d是考试的天数,h是需要复习的天数
priority_queue<PLL, vector<PLL>, greater<PLL> >q;
int main() {
//freopen("intelligent.in", "r", stdin);
//freopen("intelligent.out", "w", stdout);
while (cin >> n && n) {
p.clear(), f.clear(), res.clear();
q=priority_queue<PLL, vector<PLL>, greater<PLL> >();//清空优先队列
p.emplace_back(0LL, -1LL);
for (int i = 1; i <= n; i++)
scanf("%I64d%I64d", &exam_day[i], &review_day[i]), p.emplace_back(exam_day[i], i), review_day[i]++;
cin >> m;
long long t1,t2;
for (int i = 1; i <= m; i++)
scanf("%I64d%I64d", &t1, &t2), p.emplace_back(t1, -2LL), p.emplace_back(t2, -1LL);
sort(p.begin(), p.end());
long long cnt = 0;
for (int i = 0; i < (int)p.size(); i++) {
if (p[i].second == -2)
cnt += p[i].first - p[i - 1].first - 1;
else if (p[i].second != -1 and p[i].second != -2) {
cnt += p[i].first - p[i - 1].first;
f.emplace_back(p[i].second,cnt);
cnt = 0;
}
}
for (int i = f.size() - 1; i >= 0; i--) {
q.push(PLL(review_day[f[i].first], f[i].first));
for (long long t = f[i].second; t > 0 && !q.empty();) {
PLL top = q.top(); q.pop();
long long u = top.first, id = top.second;
if (u <= t)
t -= u, res.push_back(id);
else
q.push(PLL(u - t, id)), t = 0;
}
}
cout << res.size() << endl;
for (int i = 0; i < (int)res.size(); i++)
printf("%d%c", res[i], " \n"[i + 1 == (int)res.size()]);
}
return 0;
}