分析
用一个数据结构存储每一个商品,使用大根堆$q$对每一个商品进行存储。
用哈希表$del$记录该商品是否被删除
由于遍历优先队列会让队列变空,所以用另一个优先队列$temp$存储出队的元素,最后再把所有元素返还给$q$
C++ 代码
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
struct node{
int Id,id,sc; //商品种类Id,第id个商品,该商品得分sc
bool operator<(const node &p) const{ //由于默认为大根堆,所以所有的比较都应该反过来
if(sc!=p.sc) return sc<p.sc;
if(Id!=p.Id) return Id>p.Id;
return id>p.id;
}
};
priority_queue<node> q; //大根堆q
map<PII,int> del; //判断该商品是否删除 (pair<商品种类,第几个商品>)
int m,n,OP;
int main()
{
scanf("%d%d",&m,&n);
int cId,cid,cval;
for(int i=0;i<n;i++)
{
scanf("%d%d",&cid,&cval);
for(int j=0;j<m;j++)
q.push({j,cid,cval});
}
scanf("%d",&OP);
char op[2];
while(OP--)
{
scanf("%s",op);
if(*op=='1')
{
scanf("%d%d%d",&cId,&cid,&cval);
q.push({cId,cid,cval}); //增加操作,将商品加入到优先队列q
}
else if(*op=='2'){ //删除操作,在del中将商品的标记为1
scanf("%d%d",&cId,&cid);
del[{cId,cid}]=1;
}
else{ //查询操作
priority_queue<node> temp; //由于遍历优先队列会让队列变空,所以用另一个队列temp存储出队的元素
int tot,len[55]; //len:每个种类的商品要挑选的元素
memset(len,0,sizeof len);
vector<int> ans[55]; //答案数组
scanf("%d",&tot); //一共要选出的商品数量
for(int i=0;i<m;i++) //每个集合要选出的商品数量
scanf("%d",&len[i]);
while(q.size() && tot)
{
auto t=q.top(); q.pop();
// cout<<t.Id<<" "<<t.id<<" "<<t.sc<<endl;
temp.push(t);
if(!del[{t.Id,t.id}]) //如果该商品没有被删除,能够选择
{
if(len[t.Id]) //如果该类商品还没选完
{
ans[t.Id].push_back(t.id);
//选了一个物品,该类物品个数和总共能够选择的个数都减去1
len[t.Id]--;
tot--;
}
}
}
while(temp.size()) //将temp中的元素返还给q
{
auto t=temp.top(); temp.pop();
q.push(t);
}
for(int i=0;i<m;i++) //输出答案
{
if(!ans[i].size()) puts("-1");
else{
for(auto x:ans[i]) cout<<x<<" ";
cout<<endl;
}
}
}
}
return 0;
}
第三十四行那里记得加上一个del[{cId,cid}] = 0;不然会WA
因为如果一个商品被删除了又被加进来了需要重新标记