CCF 試題編號: 201909-4 試題名稱: 推薦系統

這題是stl的綜合應用,map要想快,直接上unordered_map,這樣查詢接近O(1),是不是很嗨皮。
思路其實還是很簡單的,type+id做個Hash,由於set.insert的第一個返回值是指向該插入元素的迭代器,所以,對於每一個type+id我們都可以存下它對應的迭代器,這樣刪除不就很快了嗎,省去查找。
這題是我第一次用c++11的語法, 原諒我的low,嘻嘻,auto還挺好用。

#include <bits/stdc++.h>
using namespace std;

const long long BASE=1e10;

struct Pair {
    long long score,hash_val;
    Pair(long long s,long long h) {
        score=s;
        hash_val=h;
    }
    bool operator < (const Pair &b) const {
        if (score!=b.score) {
            return score>b.score;
        }
        long long id1=hash_val%BASE,id2=b.hash_val%BASE;
        long long type1=hash_val-id1,type2=b.hash_val-id2;
        if (type1!=type2) {
            return type1<type2;
        }
        return id1<id2;
    }
};

set<Pair> s;
// set<pair<long long,long long> > del;
//unordered_map<long long,long long>mp;
unordered_map<long long,set<Pair>::iterator >mp;
long long num[55],top[55],total,totaltop;
vector<long long> ans[55];
long long M,N;

long long Hash(long long type,long long id)
{
	return type*BASE+id;
}

void select()
{
    memset(num,0,sizeof(num));
    long long cnt=0;
//    for (set<Pair>:: iterator it=s.begin();it!=s.end()&&cnt<total;it++) {
//        long long id=it->hash_val%BASE,type=it->hash_val/BASE;
//
////        printf("SELECT: \n");
////        printf("type: %I64d id: %I64d\n",type,id);
//        if (num[type]<top[type]) {
//            cnt++;
//            num[type]++;
//            ans[type].push_back(id);
////            printf("IN:\n");
////            printf("type: %I64d id: %I64d\n",type,id);
//        }
//        else continue;
//    }

    for (auto it:s) {
        long long id=it.hash_val%BASE,type=it.hash_val/BASE;
        if (num[type]<top[type]) {
            num[type]++;
            cnt++;
            ans[type].push_back(id);
        }
        if (cnt==total||cnt==totaltop) break;
    }
//    printf("ANS:\n");
//    for (int i=0;i<M;i++) {
//        for (int j=0;j<ans[i].size();j++) {
//            printf("%I64d ",ans[i][j]);
//        }
//        puts("");
//    }
//    puts("");
}

void print() {
    for (set<Pair>::iterator it=s.begin();it!=s.end();it++) {
        printf("sc:%I64d type:%I64d id:%I64d\n",it->score,it->hash_val/BASE,it->hash_val%BASE);
    }
    puts("");
}

int main()
{
//    long long hash_val=Hash(12,23);
//    printf("%I64d %I64d\n",hash_val%BASE,hash_val-hash_val%BASE);
//
//    s.insert(Pair(5,Hash(2,1)));
//    s.insert(Pair(5,Hash(2,2)));
//    s.insert(Pair(6,Hash(7,2)));
//    mp[Hash(1,1)]=s.insert(Pair(5,Hash(1,1))).first;
//    s.erase(mp[Hash(1,1)]);
//    for (set<Pair>::iterator it=s.begin();it!=s.end();it++) {
//        printf("%lld %lld %lld\n",it->score,it->hash_val%BASE,it->hash_val-it->hash_val%BASE);
//    }
    freopen("in.txt","r",stdin);
    long long sc,id,opnum,op,type,comm;
    scanf("%I64d%I64d",&M,&N);
    for (int i=0;i<N;i++) {
        scanf("%I64d%I64d",&id,&sc);
        for (int j=0;j<M;j++) {
            mp[Hash(j,id)]=s.insert(Pair(sc,Hash(j,id))).first;
        }
    }
//    print();
    scanf("%I64d",&opnum);
    for (int i=0;i<opnum;i++) {
        scanf("%I64d",&op);
        if (op==1) {
            scanf("%I64d%I64d%I64d",&type,&comm,&sc);
            mp[Hash(type,comm)]=s.insert(Pair(sc,Hash(type,comm))).first;
//            print();
        }
        else if (op==2) {
            scanf("%I64d%I64d",&type,&comm);
            s.erase(mp[Hash(type,comm)]);
//            print();
        }
        else {
            scanf("%I64d",&total);
            totaltop=0;
            for (int j=0;j<M;j++) {
                scanf("%I64d",&top[j]);
                totaltop+=top[j];
                ans[j].clear();
            }
//            print();
            select();
            for (int j=0;j<M;j++) {
                if (ans[j].size()==0) {
                    printf("-1\n");
                }
                else {
                    int anssize=ans[j].size();
//                    for (int k=0;k<anssize;k++){
//                        printf("%I64d",ans[j][k]);
//                        if (k==anssize-1) putchar('\n');
//                        else putchar(' ');
//                    }
                    for (int i=0;i<anssize;i++) {
                        printf("%I64d",ans[j][i]);
                        if (i==anssize-1) {
                            putchar('\n');

                        }
                        else {
                            putchar(' ');
                        }
                    }
                }
                ans[j].clear();
            }
        }
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章