ccf认证 201909-4
主要思路是:
- 用优先级队列数组来储存每一个类别的商品,优先级队列的元素是自定义的结构体,里面有cls、id、score三个元素,并且根据题目的排序要求重载了 < 运算符
- 用一个map数组来存储关于商品删除的信息,以配合优先级队列进行实现隐式的删除操作
- 增加商品时,只要添加进入优先级队列即可
- 删除商品时,不对优先级队列进行操作,只设置相应的deleted状态位true,在查询操作时要跳过deleted为true的元素
- 查询时,建立一个总优先级队列PQ,将每个类中排名最高的元素放进优先级队列,之后进行循环,每次访问PQ的top,如果该类名额已经用完,则continue,否则将该类对应的优先级队列进行pop,以使得接下来的元素能够上来并加入PQ中。对于pop出来的元素,用ans向量记录,在输出时输出ans向量,并重新将元素push进去
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
using namespace std;
struct node {
int cls, id, score;
friend bool operator<(const node &a, const node &b) {
if (a.score != b.score)
return a.score < b.score;
return a.cls != b.cls ? a.cls > b.cls : a.id > b.id;
}
node() { }
node(int _cls, int _id, int _sco): cls(_cls), id(_id), score(_sco) { }
};
bool cmp(const node &a, const node &b) {
return a.id < b.id;
}
const int maxm = 52;
const int maxn = 30010;
priority_queue<node> all[maxm];
int n, m;
map<int, bool> deleted[maxm];
int main() {
cin >> m >> n;
for (int i = 0; i < n; i++) {
int id, score;
cin >> id >> score;
for (int j = 1; j <= m; j++)
all[j].push(node(j, id, score));
}
int op_num;
cin >> op_num;
for (int i = 0; i < op_num; i++) {
int op;
cin >> op;
if (op == 1) {
int type, id, sco;
cin >> type >> id >> sco;
type++;
all[type].push(node(type, id, sco));
deleted[type][id] = false;
} else if (op == 2) {
int type, id;
cin >> type >> id;
type++;
deleted[type][id] = true;
} else {
int K;
vector<int> k_i(m+1, 0);
priority_queue<node> PQ;
vector<node> ans[m+1];
cin >> K;
for (int j = 1; j <= m; j++) {
cin >> k_i[j];
}
for (int j = 1; j <= m; j++) {
while (!all[j].empty() && deleted[j][all[j].top().id])
all[j].pop();
if (!all[j].empty())
PQ.push(all[j].top());
}
while (!PQ.empty() && K) {
node tmp = PQ.top(); PQ.pop();
if (k_i[tmp.cls] <= 0) {
continue;
}
K--;
k_i[tmp.cls]--;
ans[tmp.cls].push_back(tmp);
all[tmp.cls].pop();
while (!all[tmp.cls].empty() && deleted[tmp.cls][all[tmp.cls].top().id] == true) {
all[tmp.cls].pop();
}
if (!all[tmp.cls].empty()) {
PQ.push(all[tmp.cls].top());
}
}
for (int j = 1; j <= m; j++) {
//sort(ans[j].begin(), ans[j].end(), cmp); //按题目是要排序的,但排序了只有60分,不排序提交100分
for (auto &e : ans[j]) {
cout << e.id << " ";
all[e.cls].push(e);
}
if (ans[j].empty())
cout << -1;
cout << endl;
}
}
}
return 0;
}
/*
2 3
1 3
2 2
3 1
8
3 100 1 1
1 0 4 3
1 0 5 1
3 10 2 2
3 10 1 1
2 0 1
3 2 1 1
3 1 1 1
*/