题目分析
1、m类商品,每类商品初始为n个
2、推荐商品总阈值K,各类商品也有阈值k
3、商品清单,可以 【增加】、【删除】,【输出】
4、输出每类商品,没有的话-1,有的话按照编号由小到大顺序输出
解题策略
1、先看测试点
一般109就是题目暗示用int,不能开数组散列
首先想到的是使用priority_queue优先级队列,队列中的元素自动有序(满足这个条件的还有set集合)
然后再考虑是m个优先级队列还是一个优先级队列?
从三个方面(增加,删除,输出)分析。
(1)【增加】,type,commodity,score多个队列和一个队列没什么差别,set也可以。
(2)【删除】,只给出type,commodity,从优先级队列中随机删除某个元素是非常困难的,因为队列不支持随机访问。------------- 具有相同有序性质的容器set,支持随机访问,删除容器内的时间复杂度为logN,N为容器内的元素数量,set.erase(value),需要知道score。score和<type,commodity>相关。需要实现<type,commodity>到score的映射,不能开二维数组,commodity的阈值为109,可以使用map或者unordered_map来实现。
map<int,bool> mg[55]
unordered_map<int,bool> mg[55]
(3)【输出】,所有商品一起参与排序,根据输出要求使用vector<int> out[55]来存储推荐的商品。
如果是多个队列或者集合?每确定一个商品,需要遍历一遍m个队列或者集合。而单个队列则不需要。
每确定一个商品,那么这个商品就不能参与之后的比较,如果是队列的话,因为不支持随机访问,必须出队列,最终输出后再push进来,太麻烦啦。set可以弥补这个缺点。再考虑到多个set需要记录当前type商品数到了什么位置,单个set不需要。
综合以上考虑,确定使用单个set来存储商品,并且可以删除操作可以物理上删除,也可以直接用一个标志位来表示就行了,更简单快速一点。
60分找不到错误,到网上一搜发现是测试用例的问题,不需要对out[i]进行排序,直接按顺序输出。😔
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <unordered_map>
#include <set>
#include <vector>
using namespace std;
int m,n;
struct goods{ //商品结构体,定义排列序列
int type;
int ID;
int score;
goods(int a,int b,int c)
{
type = a;
ID = b;
score = c;
}
friend bool operator <(goods a,goods b) //重载<,对set序列进行定义
{
if(a.score == b.score)
{
if(a.type == b.type)
return a.ID < b.ID;
else
return a.type < b.type;
} else
return a.score > b.score;
}
};
set<goods> sg; //使用一个集合足够
unordered_map<int,bool> isDelete[55]; //删除<type,commodity>
vector<int> out[55]; //输出统计
int main()
{
scanf("%d %d",&m,&n);
int i,j;
int a,b,c;
for(i=0;i<n;i++) //输入初始化数据
{
scanf("%d %d",&b,&c);
for(j=0;j<m;j++)
sg.insert(goods(j,b,c));
}
int op,index;
scanf("%d",&op);
while(op--)
{
scanf("%d",&index);
if(index == 1) //增加
{
scanf("%d %d %d",&a,&b,&c);
sg.insert(goods(a,b,c));
} else if(index == 2) //删除
{
scanf("%d %d",&a,&b);
isDelete[a][b]=true; // 标记商品类型a,商品号b为已删除
} else
{
int K,ks[55]; //最大数量
scanf("%d",&K);
for(i=0;i<m;i++)
{
scanf("%d",&ks[i]);
out[i].clear(); //完成对out的重置
}
set<goods>::iterator it;
for(it=sg.begin();it!=sg.end();it++)
{
a = it->type;
b = it->ID;
c = it->score;
if( ks[a]>0 && !isDelete[a][b])
{
out[a].push_back(b);
ks[a]--;
K--;
}
for(i=0;i<m;i++)
if(ks[i] > 0)
break;
if(i==m || K==0) // 总数K 或者 每类商品都到达阈值
break; // 跳出循环
}
// 开始输出
for(i=0;i<m;i++)
{
// sort(out[i].begin(),out[i].end()); // 对商品序号进行排序
if(out[i].empty())
printf("-1\n");
for(j=0;j<out[i].size();j++)
printf("%d%c",out[i][j],j==out[i].size()-1?'\n':' ');
}
}
}
return 0;
}