zoukankan      html  css  js  c++  java
  • 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
    
  • 相关阅读:
    了解HTTP Header之User-Agent和HTTP协议的响应码
    怎样才算一个优秀的管理者
    ldpi、mdpi、hdpi、xhdpi、xxhdpi (无内容,待填)
    手把手教做小偷采集
    java中碰到无法解决的问题:无法访问类的getter访问器
    简单的加密解密处理
    Java中处理二进制移位
    Java中实现String.padLeft和String.padRight
    这短短几行代码价值一万
    从一篇文章中检查特定单词出现数量和第一次出现位置
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/15255245.html
Copyright © 2011-2022 走看看