HDU - 6003 Problem Buyer题解(贪心选择算法,鸽巢原理,优先队列维护)
16年的ccpc final题,题目不长,但是读题对于我这种蒟蒻还是看了半天,读懂后大概推测是贪心算法,用优先队列维护一个题目区间能够AC。
具体题解和分析鸽了,以后用空再写。
稍微加了点注释希望有帮助:
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<ctime>
using namespace std;
const int inf = 0x3f3f3f3f;
clock_t START, END;
struct difficultyRange {
int l, r;
bool operator < (const difficultyRange& t)const {
return (l == t.l) ? (r > t.r) : (l < t.l);//l升序,l相等时r降序(其实r怎么排序都无所谓)
}
}dr[100010];
int main() {
std::ios::sync_with_stdio(false);//不关闭同步流会使读取速度过慢,这题经过测试只有关闭才能ac
int T, N, M, c[100010];
cin >> T;
for (int ii = 1; ii <= T; ii++) {
//数据输入
cin >> N >> M;
for (int i = 1; i <= N; i++) {
cin >> dr[i].l >> dr[i].r;
}
for (int i = 1; i <= M; i++) {
cin >> c[i];
}
START = clock();
//排序题库和题
sort(dr + 1, dr + 1 + N);
sort(c + 1, c + 1 + M);
int Max = -inf;
int j = 1;
priority_queue<int, vector<int>, greater<int> > Q;//存放当前能够满足该题的区间的右端(队首为最小右端)
for (int i = 1; i <= M; i++) {//遍历每一个题目,确定 1.其对应题库内题目 以及 2.其题库内的最小购买数
//这俩个while循环能保证队列内永远是此时题目所符合的题库范围
while (!Q.empty() && Q.top() < c[i])
Q.pop();//由于此时的题目难度更高了,可能原来的左端会不满足,这里将不满足的题目出队
while (j <= N && dr[j].l <= c[i]) {
if (dr[j].r >= c[i]) {
Q.push(dr[j].r);//将满足条件的题库内题目的右端入队
}
j++;
}
Max = max(Max, N - (int)Q.size() + 1);//Q.size()是题库内满足我们要出的题目的难度范围的题目个数,N-size+1即最小的题库选择数量,
if (Max > N)
break;
if (!Q.empty())
Q.pop();//将右端最小的值贪心选择掉,接下来这个题目范围不能继续去匹配我们要出的题目
}
if (Max > N)
cout << "Case #" << ii << ": IMPOSSIBLE!" << endl;
else
cout << "Case #" << ii << ": " << Max << endl;
END = clock();
double endtime = (double)(END - START) / CLOCKS_PER_SEC;
cout << "Total time:" << endtime * 1000 << "ms" << endl;
}
return 0;
}