CSP201909-4 推荐系统(set)

非常典型的csp之用stl数据结构xjb乱搞的题。要执行的操作是增加删除和查询,考虑到输入规模,每次操作的复杂度必须是log的(当然可m可以看作比较小的常数)。优先队列可以很好地实现插入和查询,但是删除的话最坏复杂度是O(n)的,pass。因此只剩下一个选择,就是set。因为这个题的输入保证商品两两不同(综合score,id和type一起看的话)因此不用multiset,只用普通的set即可。考虑到商品得分相同时的选取原则,排序策略为:

bool operator < (const good & o) const {
		if(score != o.score) return score > o.score;
		else if(cate != o.cate) return cate < o.cate;
		else return id < o.id;
	}

这样就能保证满足条件的最优选取原则了。

具体来说,对于插入操作,直接构造结构体然后插入set,同时把type和id构成的pair为键对应的值设置为score(方便二分查找);对于删除操作,根据输入的type和id找到score,然后根据这三者创建结构体,在set中二分查找并删除;对于查询操作,按照题意遍历set模拟即可。

#include <bits/stdc++.h>
using namespace std;
int n, m;
struct good {
	int cate, id, score;
	bool operator < (const good & o) const {
		if(score != o.score) return score > o.score;
		else if(cate != o.cate) return cate < o.cate;
		else return id < o.id;
	}
};
set<good> s;
int cnt[100005];
map<pair<int,int>, int> mp;
int K, k[500];
vector<int> ans[505];
int main() {
	cin >> m >> n;
	for(int i = 1; i <= n; i++) {
		int id, score;
		scanf("%d%d", &id, &score);
		for(int j = 1; j <= m; j++) {
			good tmp;
			tmp.id = id, tmp.score = score;
			tmp.cate = j - 1;
			s.insert(tmp);
			pair<int, int> pii = make_pair(j - 1, id);
			mp[pii] = score;
		}
	}
	int opnum;
	cin >> opnum;
	for(int i = 0; i < opnum; i++) {
		int op;
		scanf("%d", &op);
		if(op == 1) {
			int type, commodity, score;
			scanf("%d%d%d", &type, &commodity, &score);
			good tmp;
			tmp.cate = type, tmp.id = commodity, tmp.score = score;
			pair<int, int> pii = make_pair(type, commodity);
			mp[pii] = score;
			s.insert(tmp);
		} else if(op == 2) {
			int type, commodity;
			scanf("%d%d", &type, &commodity);
			pair<int, int> pii = make_pair(type, commodity);
			good cpy;
			cpy.cate = type, cpy.id = commodity, cpy.score = mp[pii];
			multiset<good>::iterator it = s.lower_bound(cpy);
			if(it != s.end()) s.erase(it);
			mp.erase(pii);
		} else {
			scanf("%d", &K);
			for(int j = 0; j < m; j++) {
				scanf("%d", &k[j]);
				ans[j].clear();
			}
			vector<good> tmp;
			int tot = 0;
			for(auto x : s) {
				if(tot == K) break;
				if(ans[x.cate].size() < k[x.cate]) {
					ans[x.cate].push_back(x.id);
					tot++;
				} else {
					continue;
				}
			}
			for(int j = 0; j < m; j++) {
				if(ans[j].size()) {
					for(int p = 0; p < ans[j].size(); p++) {
						if(p != ans[j].size() - 1) printf("%d ", ans[j][p]);
						else printf("%d
", ans[j][p]);
					}
				} else {
					puts("-1");
				}
			}
		}
	}
	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
原文地址:https://www.cnblogs.com/lipoicyclic/p/15255245.html