- 直白的实现,4秒多勉强AC。
- 题目关于输出格式的描述中,【在第r个查询操作中,第c类商品选出的商品编号,同类商品的编号从小到大输出】 应该是【在第r个查询操作中,第c类商品选出的商品编号,分数不同的商品,分数更高的,其编号在前;分数相同的商品,编号更小的,其编号在前】。
19.11.25更新:
增加注释,修改部分变量的命名
#include <iostream>
#include <map>
#include <set>
#include <vector>
using namespace std;
struct PRODUCT { // 商品,由类型和编号可唯一确定一个商品
int type; // 商品类型
int commodity; // 商品编号
PRODUCT(int _type = 0, int _commodity = 0) : type(_type), commodity(_commodity) {}
};
bool operator < (const PRODUCT& lhs, const PRODUCT& rhs) { // 类型'小'的商品优于类型'大'的商品,编号小的商品优于编号大的商品
return lhs.type != rhs.type ? lhs.type < rhs.type : lhs.commodity < rhs.commodity;
}
int main() {
cin.tie(NULL); // 开始两行,是用于提速cin和cout
ios_base::sync_with_stdio(false);
int m, n;
cin >> m >> n;
map<int, set<PRODUCT>, greater<int> > scores; // score到PRODUCT的映射,一对多。score从大到小排列,PRODUCT按重载<关系排列,见上。
map<PRODUCT, int> products; // PRODUCT到score的映射,一对一
while(n--) {
int commodity, score;
cin >> commodity >> score;
for (int type = 0; type < m; ++type) {
PRODUCT pro(type, commodity);
scores[score].insert(pro);
products[pro] = score;
}
}
cin >> n;
while (n--) {
int op;
cin >> op;
PRODUCT pro;
int score;
switch (op) {
case 1: { // 增加
cin >> pro.type >> pro.commodity >> score;
scores[score].insert(pro); // score多了新商品pro
products[pro] = score; // 记录pro分数为score
break;
}
case 2: { // 删除
cin >> pro.type >> pro.commodity;
score = products[pro]; // 先存下要被删除商品的score
products.erase(pro); // 再安全地删掉这条记录
scores[score].erase(pro); // 然后从对应score的集合里移除商品pro
if (scores[score].empty()) scores.erase(score); // 如果没有分数为score的商品了,移除这条映射关系。
break;
}
case 3: { // 查询
int K;
vector<int> k(m);
cin >> K;
for (int i = 0; i < m; ++i) cin >> k[i];
vector<vector<int> > top(m); // 在m类里,分别都选了哪些商品?记录它们的编号,以备输出
// 因为已经按题目要求,将数据排好序了。在这里,只需要从前往后取至多K个商品。
for (map<int, set<PRODUCT>, greater<int> >::iterator it = scores.begin(); it != scores.end() && K > 0; ++it) {
for (set<PRODUCT>::iterator p = it->second.begin(); p != it->second.end() && K > 0; ++p) {
if (k[p->type]-- > 0) { // 还要注意p->type类里,不能取超过k[p->type]个商品
top[p->type].push_back(p->commodity);
--K;
}
}
}
for (int i = 0; i < m; ++i) {
if (top[i].empty()) {
cout << "-1" << endl;
} else { // 注意,此处不能再排序top[i]。即,编号大的商品如果其分数大,应该输出在编号小的商品前面。
for (int j = 0; j < top[i].size(); ++j) cout << top[i][j] << " ";
cout << endl;
}
}
break;
}
}
}
return 0;
}