【题目链接】
【题目考点】
1. 堆
2. 大量数据输入输出
当输入数据量达到 1 0 6 10^6 106规模,或输出数据量达到 1 0 5 10^5 105规模时,有以下两种输入输出方法:
- 用scanf/printf
- 解除IO同步,IO解绑
ios::sync_with_stdio(false);
cin.tie(0);
并使用cout << '\n'
代替cout << endl;
【解题思路】
设结构体类型Person表示一个患者,包含属性:名字,病情优先级。
设优先队列(堆),里面保存Person类型的对象,优先级定义为:病情优先级高的人更优先。
输入数据,遇到push时,生成一个患者,加入优先队列。遇到pop时,取优先队列的队头(堆顶),而后出队(删除堆顶)。如果优先队列为空,输出none。
添加和删除的患者数量达到 1 0 5 10^5 105,如果使用优先队列(堆),那么添加、删除的复杂度都是 O ( l o g n ) O(logn) O(logn),整体复杂度为 O ( n l o g n ) O(nlogn) O(nlogn),是可行的。
【注意】该题输出数据量达到 1 0 5 10^5 105,因此要用scanf/printf来做输入输出,或解除IO同步,IO解绑。
【题解代码】
解法1:使用scanf/printf,使用优先队列
#include<bits/stdc++.h>
using namespace std;
struct Person
{
char name[25];
int level;
bool operator < (const Person &b) const
{
return b.level > level;//病情等级更高的更优先
}
};
int main()
{
Person per;
int n;
char s[25];
scanf("%d", &n);
priority_queue<Person> pq;//大顶堆
for(int i = 1; i <= n; ++i)
{
scanf("%s", s);
if(strcmp(s, "push") == 0)
{
scanf("%s%d", per.name, &per.level);
pq.push(per);
}
else//pop
{
if(pq.empty())
printf("none\n");
else
{
per = pq.top();
printf("%s %d\n", per.name, per.level);
pq.pop();
}
}
}
return 0;
}
解法2:解除IO同步,IO解绑,手写堆
#include<bits/stdc++.h>
using namespace std;
#define N 100005
template<class T, class IsPriorClass>
class PriorityQueue//优先队列类
{
private:
T heap[N];
int n;
IsPriorClass isPrior;//仿函数对象:用于比较两元素的优先级
void shiftUp(int i)//第i结点上移
{
if(i == 1)//p是根结点
return;
if(isPrior(heap[i/2], heap[i]))
{
swap(heap[i], heap[i/2]);
shiftUp(i/2);
}
}
void shiftDown(int i)//第i结点下沉
{
if(i > n/2)//如果i是叶子结点
return;
int sel;//选择交换的结点位置
if(2*i+1 <= n && isPrior(heap[2*i],heap[2*i+1]))//有右孩子且右孩子值更大
sel = 2*i + 1;
else//没有右孩子或左孩子值更大
sel = 2*i;
if(isPrior(heap[i],heap[sel]))
{
swap(heap[sel], heap[i]);
shiftDown(sel);
}
}
public:
PriorityQueue()
{
n = 0;
}
void push(T val)//堆中插入元素
{
heap[++n] = val;
shiftUp(n);
}
void pop()//删除堆顶
{
swap(heap[1], heap[n]);
n--;
shiftDown(1);
}
T top()//获取堆顶
{
return heap[1];
}
bool empty()//判断堆为空
{
return n == 0;
}
int size()//获取堆中元素个数
{
return n;
}
};
struct Person
{
string name;
int level;
};
struct Cmp
{
bool operator () (Person &a, Person &b)
{
return b.level > a.level;
}
};
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
Person per;
int a, n;
string s;
cin >> n;
PriorityQueue<Person, Cmp> pq;//病情等级更高的更优先
for(int i = 1; i <= n; ++i)
{
cin >> s;
if(s == "push")
{
cin >> per.name >> per.level;
pq.push(per);
}
else//pop
{
if(pq.empty())
cout << "none\n";
else
{
per = pq.top();
cout << per.name << ' ' << per.level << '\n';
pq.pop();
}
}
}
return 0;
}