CCF CSP 竞赛试题——推荐系统(201909-4)

  • 直白的实现,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;
}
发布了33 篇原创文章 · 获赞 4 · 访问量 8731

猜你喜欢

转载自blog.csdn.net/Touchig/article/details/103236650