题意
题目中给你m类商品每一类商品都会编号不同的n个商品
要你在某种情况下推荐出合适(分数最高)的商品
有3种操作
- 输入为1开头的增加操作,1后跟着3个数字分别为商品类别,商品编号,商品分数。
- 输入为2开头的删除操作,2后跟着2个数字分别为商品类别,商品编号。
- 输入为3开头的推荐操作,3后跟着m+1个数字其中第一个数字代表本次从所有商品中选出最大的商品数(可以不达到但不能超过),接下来m个数为每一类商品中最大选出的商品数。要求输出每类商品的推荐编号同类商品按从小到大的顺序排列。
商品选择时的比较逻辑
- 先选分数最高的
- 如果类别不同,选择类别编号最小的
- 如果类别相同,选择商品编号最小的
思路
采用set保存一个{类别,编号,分数}类,该类自己实现<运算符函数就可以解题,但是这种做法却有一个难点,删除操作时无法删除因为删除操作只给出了商品类别,商品编号,无从得知分数的信息。
解决办法:再设立一个{类别,编号}到{分数}的映射
100分选择(哈希永远滴神)
set<>
unordered_map<>
80分选择 超时(平衡树暂时的神)
set<>
map<>
20分选择
vector<> + sort()
代码
#include <iostream>
#include <map>
#include <unordered_map>
#include <set>
#include <vector>
#include <fstream>
#include <sstream>
#include <algorithm>
using namespace std;
int m, n, op_num;
vector<vector<int>> ops;
class Commodity {
public:
int type;
int number;
int score;
Commodity(const int& a, const int& b, const int& c) :type(a), number(b), score(c) { }
bool operator <(const Commodity& b)const {
if (score != b.score)
return score > b.score;
else if (type != b.type)
return type < b.type;
else
return number < b.number;
}
};
class pair_hash {
public:
template<typename T1, typename T2>
size_t operator()(const pair<T1, T2>& a)const {
return hash<T1>{}(a.first) ^ hash<T2>{}(a.second);
}
/*size_t operator()(const pair<int, int>& a)const {
return hash<int>{}(a.first) ^ hash<int>()(a.second);
}*/
};
unordered_map<pair<int, int>, int, pair_hash> maps;
//map<pair<int, int>, int> maps;//80分警告
set<Commodity> cs;
void excuteOps() {
for (const auto& op : ops) {
switch (op[0])
{
case 1:
cs.insert({ op[1],op[2],op[3] });
maps[{op[1], op[2]}] = op[3];
break;
case 2:
cs.erase({ op[1],op[2],maps[{op[1],op[2]}] });
maps.erase({ op[1], op[2] });
break;
case 3:
int k = op[1];
vector<int> counts(op.begin() + 2, op.end());//计数m个类中每个类选出的个数
vector<vector<int>> resv;//保存结果
resv.resize(m);
for (const auto& x : cs) {
if (!k)break;
else if (counts[x.type]) {
resv[x.type].push_back(x.number);
--counts[x.type];
--k;
}
}
for (auto& x : resv) {
if (x.size() == 0)cout << -1;
//sort(x.begin(), x.end());//同类从小到大输出,疑问:按道理应该是要有的但不知为什么只要加了一句就只有60分
for (const auto& xx : x) {
cout << xx << ' ';
}
cout << endl;
}
break;
}
}
}
//#define DEBUG
int main() {
#ifdef DEBUG
fstream cin("input.txt");
#endif // DEBUG
cin >> m >> n;
for (int i = 0; i < n; ++i) {
int id, score;
cin >> id >> score;
for (int j = 0; j < m; ++j) {
maps[{j, id}] = score;
cs.insert({ j,id,score });
}
}
cin >> op_num;
ops.resize(op_num);
cin.get();//去回车
for (int i = 0; i < op_num; ++i) {
stringstream strs;
string str;
int temp;
getline(cin, str);
strs << str;
while (strs >> temp)
ops[i].push_back(temp);
}
excuteOps();
}
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