本题梳理:
共有m类产品:0~m-1类;
“对于每个app新用户,每类商品初始有编号不同的n个商品”:这句话的意思是说开始输入时各类产品有n个相同的产品,这个相同包括产品编号和评分都相同。
然后可以进行操作:插入/删除/查询
插入:指明类别和编号和评分
删除:指明类别和编号
查询:从所有的产品中查询评分前k个产品,且是尽量查询(即能找到多少是多少最多不过k个)
而且每一类产品也有个数限制且也有个数限制。
原则是:(1)若两个评分相同且在同一类中,则选择编号小的。(2)若两个评分相同且不在同一类中,则选择类号小的。
首先是超时代码,得了10分:
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
struct Good{
int type;
int commodity;
int score;
};
class compare{
public:
bool operator()(const Good g1,const Good g2)
{
if(g1.score == g2.score&&g1.type == g2.type)
{
return g1.commodity<g2.commodity;
}else if(g1.score == g2.score&&g1.type != g2.type)
{
return g1.type<g2.type;
}else
return g1.score > g2.score;
}
};
Good good;
int n,m,commodity,score;
set<Good,compare> goods;
set<Good,compare>::iterator it;
vector<int> chose_good[52];//存储各类已选商品的编号
int cns[52];//记录各类已选商品的个数
void my_print(Good good)
{
cout<<good.type<<" "<<good.commodity<<" "<<good.score<<endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int i,j,opnum,op,threshold,type_threshold[52],type,commodity;
cin>>m>>n;
for(i=0;i<n;i++)
{
cin>>commodity>>score;
good.commodity=commodity;
good.score = score;
for(j=0;j<m;j++)
{
good.type=j;
goods.insert(good);
}
}
cin>>opnum;
for(i=0;i<opnum;i++)
{
cin>>op;
switch(op){
case 1:
cin>>good.type>>good.commodity>>good.score;
goods.insert(good);
cout<<"添加后:"<<endl;
for_each(goods.begin(),goods.end(),my_print);
break;
case 2:
cin>>type>>commodity;
for(it=goods.begin();it!=goods.end();it++)
{
if(it->type == type&&it->commodity == commodity) break;
}
if(it!=goods.end())
goods.erase(it);
cout<<"删除后:"<<endl;
for_each(goods.begin(),goods.end(),my_print);
break;
case 3:
for(j=0;j<52;j++)
{
cns[j]=0;
chose_good[j].clear();
}//cns[51]代表已选总数。
cin>>threshold;
for(j=0;j<m;j++)
{
cin>>type_threshold[j];//各类别的限制
}
for(it=goods.begin();cns[51]<threshold&&it!=goods.end();it++)
{
if(cns[it->type] < type_threshold[it->type])
{
chose_good[it->type].push_back(it->commodity);
cns[51]++;
cns[it->type]++;
}
}
for(j=0;j<m;j++)
{
if(chose_good[j].size()==0)
{
cout<<"-1"<<endl;
continue;
}
for(vector<int>::iterator it=chose_good[j].begin();it!=chose_good[j].end();it++)
{
if(it==chose_good[j].begin())
cout<<*it;
else
cout<<" "<<*it;
}
cout<<endl;
}
break;
}
}
return 0;
}
然后是100分代码,参考了某位大佬的“惰性删除”思想,虽然不知道是哪里的思想,但是不超时了。也没怎么弄懂是怎么节省时间的(后来不也经历了先查询后删除吗)。
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
struct Good{
int type;
int commodity;
int score;
};
struct Del{
int type;
int id;
Del(int _type, int _id){
type=_type; id=_id;
}
bool operator < (const Del &rhs) const{
if(type==rhs.type) return id<rhs.id;
return type<rhs.type;
}
};
class compare{
public:
bool operator()(const Good g1,const Good g2)
{
if(g1.score == g2.score&&g1.type == g2.type)
{
return g1.commodity<g2.commodity;
}else if(g1.score == g2.score&&g1.type != g2.type)
{
return g1.type<g2.type;
}else
return g1.score > g2.score;
}
};
Good good;
int n,m,commodity,score;
set<Good,compare> goods;
set<Del> has_del;
set<Good,compare>::iterator it;
vector<int> chose_good[52];//存储各类已选商品的编号
int cns[52];//记录各类已选商品的个数
void my_print(Good good)
{
cout<<good.type<<" "<<good.commodity<<" "<<good.score<<endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int i,j,opnum,op,threshold,type_threshold[52],type,commodity;
cin>>m>>n;
for(i=0;i<n;i++)
{
cin>>commodity>>score;
good.commodity=commodity;
good.score = score;
for(j=0;j<m;j++)
{
good.type=j;
goods.insert(good);
}
}
cin>>opnum;
for(i=0;i<opnum;i++)
{
cin>>op;
switch(op){
case 1:
cin>>good.type>>good.commodity>>good.score;
goods.insert(good);
break;
case 2:
cin>>type>>commodity;
has_del.insert(Del(type, commodity)); //将该商品加入删除表中,实行惰性删除
break;
case 3:
for(j=0;j<52;j++)
{
cns[j]=0;
chose_good[j].clear();
}//cns[51]代表已选总数。
cin>>threshold;
for(j=0;j<m;j++)
{
cin>>type_threshold[j];//各类别的限制
}
for(it=goods.begin(); cns[51]<threshold && it!=goods.end();){
//该类商品未选满,查看该商品是否已删除
if(cns[(*it).type]<type_threshold[(*it).type]){
if(has_del.find(Del((*it).type, (*it).commodity))!=has_del.end()){
//存在于删除表中
goods.erase(it++); //删除该元素,迭代器自增
}
//未删除
else{
++cns[(*it).type];
++cns[51];
chose_good[(*it).type].push_back((*it).commodity);
it++;
}
}
else it++;
}
for(j=0;j<m;j++)
{
if(chose_good[j].size()==0)
{
cout<<"-1"<<endl;
continue;
}
for(vector<int>::iterator it=chose_good[j].begin();it!=chose_good[j].end();it++)
{
if(it==chose_good[j].begin())
cout<<*it;
else
cout<<" "<<*it;
}
cout<<endl;
}
break;
}
}
return 0;
}