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的不同,大家要去其他文章仔细研究一下比较好。