201909-4 csp推荐系统

csp 201990 -4 推荐系统

题目描述

在这里插入图片描述
在这里插入图片描述

解题思路

这道题其实就是简单的模拟题,难点在于如何设计表,如何提高效率。如果单纯使用vector在数据量比较大的情况下会出现超时。我在做题的时候考虑过使用vector来解题,会出现超时的情况,因为插入和删除操作会导致vector内位置移动,会有大量操作。这一题可以使用set来解题,首先set的底层实际上是 一个红黑树,即平衡二叉树,这样插入的效率基本上保持在logN。set是自动有序的,那么对于查找操作也很方便,其效率基本保持在N。实际上比较耗时的是删除操作。我本来的想法是遍历整张表,根据type 和id 找到要删除的点之后再进行删除操作,但是这样操作的效率为N,如果我再维持一张表,根据提供的type和id ,我能够得到完整的商品信息,完整的商品信息对于set表来说是key,根据这个key再去表中查找删除,其中查找的效率仅为logN,相对来说速度有所提升。

  • 我本来以为对于删除操作,直接使用遍历时可以的,并不是非常耗时,但是我这样做会产生超时的问题,代码的分数时10分。于是我就牺牲空间换时间,使用更快的方法。这样才是满分。虽然我以为时间上似乎并没有差距很大。当然还可以不从set表中删除这个节点,直接标记map表,标记删除,在实际查询时掠过这些被标记删除的数据即可。
  • 这道题在官方测评上好像是有问题的,如果把最终结果按照题目意思排序,只有60分。如果不排序就是满分。我认为这是bug…
  • 下面的是满分代码,没有进行排序,如果排序的话可以使用set存储最终结果而不使用vector 或者存储完了之后排序。
#include<stdio.h>
#include <iostream>
#include <vector>
#include <stdlib.h> 
#include <algorithm>
#include <set>
#include <map> 
 
using namespace std;
class GOOD {
	public:int type;
	public:int id;
	public:int score;
	public:GOOD(){
		type = -1;
		id = -1;
		score = -1;
	}
	public:GOOD(int _type,int _id, int _score) {
		type = _type;
		id = _id;
		score = _score;
	}
	bool operator < (const GOOD d) const {
		return score > d.score || (score == d.score && type < d.type) || (score == d.score && type == d.type && id < d.id);
	}

};

struct INDEX {
	int type , id;
	INDEX(int _type , int _id):type(_type) , id(_id){}
	bool operator < (const INDEX d) const {
		return type < d.type || (type == d.type && id < d.id);
	}
};

int main() {
	int m, n;
	scanf("%d%d",&m,&n);
	set<GOOD> dataMap;
	map<INDEX , int> delMap;
	for (int i=0; i<n; i++) {
		int id, score;
		scanf("%d%d",&id,&score);
		for (int j=0;j<m;j++) {
			dataMap.insert(GOOD(j,id,score));
			delMap[INDEX(j,id)]= score;	
		}
	}
	int opnum ;
	scanf("%d",&opnum);
	while(opnum--) {
		int op;
		scanf("%d",&op);
		if (op == 1) { //add
			int type, commodity, sc;
			scanf("%d%d%d",&type,&commodity,&sc);
			dataMap.insert(GOOD(type,commodity,sc));
			delMap[INDEX(type,commodity)]= sc;	
		}else if (op == 2) { // delete 删除操作费时 
			int type, commodity;
			scanf("%d%d",&type,&commodity); // 迭代查询删除
			set<GOOD>::iterator it = dataMap.find(GOOD(type,commodity,delMap[INDEX(type,commodity)]));
			dataMap.erase(it);
			delMap[INDEX(type,commodity)] = -1;
		}else if (op == 3) { // query
			int sumNumber;
			int limit[100]={0};
			vector<int> res[100];
			scanf("%d",&sumNumber);
			for (int k=0; k<m;k++){
				scanf("%d",&limit[k]);
			}
			for (set<GOOD>::iterator it = dataMap.begin(); it!=dataMap.end()&&sumNumber;it++) {
				GOOD good = *it;
				if (limit[good.type]>0) {
					res[good.type].push_back(good.id);
					sumNumber--;
					limit[good.type]--;
				}
			}
			for (int p=0; p<m;p++) {
				if (res[p].size() == 0) {
					cout << "-1" ;
				}else {
					for (int h=0; h<res[p].size(); h++ ){
						if (h>0) {
							cout <<" ";
						}
						cout << res[p][h] ;						
					}
				}
				cout << endl;
			} 
		}
	}
	return 0;
}

Tips

想要做csp的模拟题,到官网上点模拟考试就好啦。关于set , vector ,map的不同,大家要去其他文章仔细研究一下比较好。

网址链接

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值