题目思路:
首先要告诉读者的是,在set和map中,内部结构为平衡二叉树,所以insert和erase并不会改变容器中其他元素的迭代器,但是vector会,它属于连续存储,所以他的push_abck和erase,insert函数都会改变其他元素的在内存中的位置。
具体做法:
使用一个set数组记录每一类型商品中的元素,由一个三元组构成(类型,编号,评分),那么,插入的话就可以往对应的set中插入三元组。那么怎么处理删除呢,set的erase有两种参数,一种是删除迭代器,一种是删除数值,那么我们要么记录迭代器,要么记录数值,很显然这里需要一个map
做法1:我们把(类型,编号)作为键,评分一直在变,所以作为值,在插入和初始化的时候就更新了map
做法2:我们把(类型,编号)作为键,迭代器作为值,这个怎么搞就成问题了,有一个冷门知识就是,set的insert函数其实是有返回值的,是一个pair,first就是迭代器,second是bool类型,表示插入是否成功。
在操作3查询的时候,我们直接遍历,每个类型的set,注意到编号可以很多,但是K只有100 , 所以对于一个集合,只取min(K,Max[i])个,那么50个set的话最多取5000个,只要在这5000个里边,排个序,取前K个,输出就行。
排序的话,第一优先级是评分,从大到小,第二优先级是类型,从小到大,第三优先级是编号,从小到大。
可是!!!!!!
会发现只有60分,说超时了,第一想法是改成C语言的输入,或者关掉同步流。提交!70分,运行超时。
这个时候我们来计算一下时间复杂度,对于插入和删除的复杂读是O(nlogn)的完全没问题,查询的复杂度,
O(m*k*log n),理论上一点问题都没有,最多多个常数,也不会导致超时,何况题目5s。
但是就是超时了,这个情况让我想起了2019的秦皇岛A题,就是卡时间,原因也是我使用map拿pair做键值,最后是把pair改成哈希使用unordered-map过的,只不过键值必须是整形,所以要哈希一下。这个题同样,把键值pair哈希掉就可以了。改用unorderde-map。查询速度接近O(1).
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 1e5+5;
struct node
{
int tp,id,sc;
node(){}
node(int a,int b,int c){
tp = a;id = b;sc = c;
}
bool operator <(const node r)const{
if(sc == r.sc){
if(tp == r.tp){
return id<r.id;
}
return tp<r.tp;
}
return sc>r.sc;
}
};
ll Hash(ll a,ll b)
{
ll ret = 0;
return (ll)a*(ll)1e10 + b;
}
unordered_map<ll,int >mp;
set<node>st[55];
int m,n;
int main()
{
mp.clear();
scanf("%d%d",&m,&n);
for(int i=1;i<=n;i++){
int id,sc;
scanf("%d%d",&id,&sc);
for(int j=0;j<m;j++){
st[j].insert(node(j,id,sc));
mp[Hash(j,id)] = sc;
}
}
int t;
scanf("%d",&t);
while(t--){
int op ;
scanf("%d",&op);
if(op == 1){
int tp,id,sc;
scanf("%d%d%d",&tp,&id,&sc);
st[tp].insert(node(tp,id,sc));
mp[Hash(tp,id)] = sc;
}
else if(op == 2){
int tp,id;
scanf("%d%d",&tp,&id);
int sc = mp[Hash(tp,id)];
st[tp].erase(node(tp,id,sc));
mp.erase(Hash(tp,id));
}
else{
int Max[55];
vector<int>v[55];
vector<node>ss;
ss.clear();
int k;
scanf("%d",&k);
for(int i=0;i<m;i++){
v[i].clear();
scanf("%d",&Max[i]);
}
for(int i=0;i<m;i++){
int cnt = 0;
set<node>::iterator it;
for(it = st[i].begin();it!=st[i].end();it++){
cnt++;
if(cnt>k ||cnt > Max[i])break;
ss.push_back((*it));
}
}
int cnt = 0;
sort(ss.begin(),ss.end());
int len = ss.size();
for(int j=0;j<len;j++){
cnt++;
if(cnt > k)break;
int tp = ss[j].tp;
int id = ss[j].id;
int sc = ss[j].sc;
v[tp].push_back(id);
}
for(int i=0;i<m;i++){
int len = v[i].size();
if(len == 0){
printf("-1\n");
}
else {
for(int j=0;j<len;j++){
printf("%d ",v[i][j]);
}
printf("\n");
}
}
//cout<<endl;
}
}
}
/*
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
*/