优先队列
一、定义
普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。通常采用堆数据结构来实现。即优先队列就为可在插入数后进行自动排序的队列。
二、定义
头文件:
#include <queue>
#include <vector>
定义:
priority_queue <int, vector<int>, greater<int> > q;//定义q为整形升序队列;
priority_queue <int, vector<int> > q;//定义q为整形降序队列;
三、基本操作
1、判空
队列名.empty()//返回值是空,为假时非空
2、求队列中实际元素的个数
队列名.size()
3、入队,入队操作前判断队列是否已满
队列名.push(x)
4、出队,出队操作前判断队列是否为空
队列名.pop()
5、取队首元素
队列名.front()
6、去队尾元素
队列名.back()
四、经典题目
Rating
一、题目
题目描述
小 L 有 n 个 CF 号,每场比赛他会使用一个账号,会得到一个 Performance,假设原 Rating 为 x,Performance 为 y,则 Rating 变为 x+y2{x+y\over 2}2x+y。
小 L 会贪心地选择自己每一次使用的号,使得 每场之后 CF Rating 之和最大,请您在每一场比赛之后输出他的 Rating 之和,保留两位小数。
换句话说,每场之前,小 L 根据当前自己所有号 Rating,选出一个号参加比赛,以最大化这场之后他的 Rating 之和。下一场时,之前的选择都会被保留,即使换一种选择可能使下一场后 Rating 和更大,也不能更换之前的选择。
输入格式
第一行两个正整数 n,m,表示号的个数和比赛场数。
接下来一行 n 个整数,表示他每个号的 Rating。
之后 m 行,每行 1 个整数,表示小 L 的 Performance。
输出格式
对于每一个询问,输出一个实数表示答案,保留两位小数。
样例
输入
5 5
2000 2100 2200 2300 2350
1900
1500
2200
2700
2000
输出
10900.00
10675.00
10912.50
11281.25
11231.25
数据范围与提示
对于 30% 的数据 $ n, m \leq 3 $ 。
对于 60% 的数据 $ n, m \leq 10^3 $ 。
对于另外 20% 的数据,m = 1 。
对于 100% 的数据,$ 1 \leq n, m \leq 10^5 $ , Rating 和 Performance 均为 $ 1 $ ~ $ 10^5 $ 之间的整数。
二、分析
思路:
此题运用优先队列,每一次用n个号中Rating的最小值参加比赛,假设原 Rating 为 x,Performance 为 y,则所损失的分数为x−y2{x-y\over 2}2x−y。
三、代码
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
priority_queue <double, vector<double>, greater<double> > q;
int n, m;
double x, ans, r, tot, p;
int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%lf", &x);
ans += x;
q.push(x);
}
for (int i = 1; i <= m; i++) {
scanf("%lf", &r);
tot = (q.top() - r) / 2;
p = (q.top() + r) / 2;
ans -= tot;
q.pop();
q.push(p);
printf("%.2lf\n", ans);
}
return 0;
}