201909-4 CSP认证 推荐系统(set + map容器)

题目思路:

       首先要告诉读者的是,在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

*/

猜你喜欢

转载自blog.csdn.net/qq_41645482/article/details/105329012