CSP 201909-4 推荐系统

  • 题目链接:推荐系统

  • 题目描述:
    在这里插入图片描述
    在这里插入图片描述

  • 题意解读:

    • 这是要维护一个商店的商品列表,商品种类一直为m种不变。一共有三种操作
    1. 添加某类商品
    2. 删除某类商品中的一个
    3. 查询商品
    • 注意一下查询时的排序,首先是按商品得分降序排,得分相同时按类别升序排,类别也相同按编号升序排。选取商品时,每类商品有数量限制,商品总数也有数量限制
  • 思路分析

    • 涉及到排序问题,可以考虑用vector存商品再用sort排序,但是这样要注意重复添加相同商品的问题,比较麻烦;或者可以set,这样不但能去重,还能在添加时自动有序
    • 删除比较麻烦,set只能用iterator删除,结合find一起用,复杂度O(logN)为了提高效率,可以不真的从set中删除,而是另外记录一下删除信息,最后查询的时候从这里看商品是否被删了。删除记录可以用散列的思想,复杂度降到O(1)。一开始想开个bool del[55][1000000010]的大数组,但是这个占内存太大了,所以改成用map做。
  • 满分代码

    #include<iostream>
    #include<set>
    #include<map>
    #include<utility>
    #include<algorithm>
    using namespace std;
    
    typedef struct PRODUCT
    {
    	int type;	//类型 
    	int id;		//编号 
    	int score; 	//得分 
    	
    	PRODUCT(int a,int b,int c):type(a),id(b),score(c){}
    	
    	//重定义<操作符,这决定了set的自动排序 
    	bool operator < (const PRODUCT &rhs) const
    	{
    		if(score!=rhs.score)
    			return score>rhs.score;
    		else if(type!=rhs.type) 
    			return type<rhs.type;
    		return id<rhs.id;			
    	}
    }PRODUCT; 
     
    set<PRODUCT> product;			//商品存储,利用set自动排序 
    map<pair<int,int>,bool> del;	//删除标记散列表 
    
    int main()
    {
    	//cin cout加速 
    	ios::sync_with_stdio(0);
    	cin.tie(0); cout.tie(0);
    	
    	//初始化商品 (m类,每类初始n个) 
    	int m,n;
    	cin>>m>>n; 
    	
    	int type,id,score;
    	for(int i=0;i<n;i++)
    	{
    		cin>>id>>score;
    		for(int j=0;j<m;j++) 		
    		{
    			product.insert(PRODUCT(j,id,score));
    			del[make_pair(type,id)] = false;
    		}
    	}
    	
    	int OPnum;
    	int cmd;
    	int K,K_[55];
    	cin>>OPnum;
    	for(int op=0;op<OPnum;op++)
    	{
    		cin>>cmd;
    		
    		if(cmd == 1)	//添加 
    		{
    			cin>>type>>id>>score;
    			product.insert(PRODUCT(type,id,score));
    			del[make_pair(type,id)] = false;
    		}
    		else if(cmd==2)	//删除 
    		{
    			cin>>type>>id;
    			del[make_pair(type,id)] = true;
    		}
    		else			//查询 
    		{		
    			cin>>K;
    			for(int i=0;i<m;i++)
    				cin>>K_[i];
    			
    			vector<int> ans[55];
    			for(set<PRODUCT>::iterator it = product.begin();it!=product.end();it++)
    			{						
    				int t = it->type;
    				int i = it->id;
    				int s = it->score; 
    			
    			    if(K_[t]>0 && !del[make_pair(t,i)])
    				{
    					ans[t].push_back(i);
    					K_[t]--;
    					if(--K<=0)
    						break;
    				}
    			}
    			 
    			for(int i=0;i<m;i++)
    			{
    				if(!ans[i].size())
    					cout<<-1<<endl;
    				else 
    				{
    					cout<<ans[i][0];
    					for(int j = 1;j<ans[i].size();j++) 
    						cout<<" "<<ans[i][j];
    					cout<<endl;
    				}
    			}
    		}
    	}
    	
    	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 
    
    
  • tips:

    1. 以下代码可以使cin/cout的速度接近printf/scanf
      ios::sync_with_stdio(0);
      cin.tie(0); cout.tie(0);
      
    2. 在定义结构体时重载<运算符,这决定了set<struct>map<struct,...>等自动有序STL容器的排序方式。升降序控制和写sortcmp函数相同
    3. 看清题啊看清题,这里我一开始把id最大值当成N的最大值了,开数组记录删除信息一直报错查了好久…
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云端FFF

所有博文免费阅读,求打赏鼓励~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值