CCF認證201909-4推薦系統

題解思路:

先說一下解題思路吧,這是一道比較明晰的模擬題,由m種物品,每一種物品都會被打分,題目要求你篩選出k個打分靠前的物品,並且這些物品的種類每一個都必須要有閾值,也就是說這個類型的不能存入超過這個閾值的數量.

那麼這一題是一個模擬題,首先梳理題意的時候就必須注意到,這是一道對所有物品得分進行排序,然後對於同分的物品又要對序號進行升序排序,直接可以想zhe到struct + set的算法,值得提一下的兩點: 1. set算法insert過後會返回一個pair<set<T>::iterator,bool>,第一個參數返回的是在set中的位置迭代器,第二個則表示插入的成功與否. 2.如果要讓struct能夠在set中排序 需要重載操作符 

bool operator<(const node& rhs)const{}  const十分重要! STL沒學好的小夥伴可以看看C++標準庫 會有很大的收穫!

那麼這一題 我們其實只要定義一個 set<Node> S;類型的集合就可,然後 按照題意重載操作符並插入到集合中,取出的時候要注意閾值問題,用vector<vector<int> > ans來存儲答案, 我借鑑了網上一個比較巧妙的寫法 if(ans[type].size() < kseq[type])  ...//insert operation . 詳細寫法見下方代碼....值得提一下的是 這裏行標表示的是物品類型.

廢話不多說 直接上AC代碼!

#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <map>
#include <set>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll m,n;
struct node{
    ll id;
    ll score;
    bool operator<(const node& rhs)const{
        if(score == rhs.score)
            return id < rhs.id;
        return score > rhs.score;
    }
    node(ll id = 0,ll score = 0):
        id(id),score(score){}
};

set<node> nodeSeq;
const ll mod = 1e9;
unordered_map<ll,set<node>::iterator> mp;
void addToQueue(){
   ll type,id,score;
   cin >> type >> id >> score;
   mp[type*mod + id] = nodeSeq.insert(node(type*mod+ id,score)).first;
}
map<ll,bool> vis;

void dropEle(){
    ll type,id;

    cin >> type >> id;
    vis[type*mod + id] = true;
    mp.erase(type*mod+id);
}
void queryData(){
    int k;
    cin >> k;
    int s = 0;
    vector<int> kseq(m);
    vector<vector<ll> > ans;
    ans.resize(m);
    for(int i = 0 ; i < m ; ++i){
        cin >> kseq[i];
        s += kseq[i];
    }

    for(auto it : nodeSeq){
        if(vis[it.id] == true) continue;
        ll type = it.id/mod;
        if(ans[type].size() < kseq[type]){
            ans[type].push_back(it.id%mod);

        }
        k--;
        if(k == 0) break;
    }
    for(auto it : ans){
        if(it.empty()){
            cout << -1 << endl;
        }else{
            for(auto j:it){
                cout << j << " ";
            }
            cout << endl;
        }
    }

}
int main(){

    cin >> m >> n;

    for(ll i = 0 ; i < n  ;++i){
        ll id,score;
        cin >> id >> score;
        for(ll type = 0 ; type < m ; ++type){
            nodeSeq.insert(node(type*1e9 + id,score));
        }
    }
    int op;
    cin >> op;
    for(int i = 0 ; i < op ; i++){
        int type;
        cin >> type;
        if(type == 1){
            addToQueue();
        }else if(type == 2){
            dropEle();
        }else if(type == 3){
            queryData();
        }
    
    }
    return 0;
}

本題反思:

這題我換了很多的寫法,一開始使用都是priority_queue<node> 優先隊列的寫法,首先發現用當下的node重載規則去排序必須反過來去寫,結果只拿了十分,結果發現我讀錯題意了,以至於我後面的vector<vector<>>模擬的寫法都沒有通過.

所以讀題很重要啊

另外 我個人感覺這題和pat甲級的table tennis一樣屬於比較噁心的STL題 吐了

 

發佈了36 篇原創文章 · 獲贊 4 · 訪問量 6417
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章