题目大意:设计一个推荐系统。用户有N次输入,每次输入的是一件商品的 id (1~N),要求从第2次输入开始推荐,即列出用户之前搜索次数最多的K件商品(不足K件没关系,但是不能超过K件)。对于搜索次数相同的,按照 id 排序。N <= 50000, K <= 10。
首先设置结构体 query记录次数和 id,然后就是根据用户每次的输入来推荐。问题主要是对于 N = 50000的量级,不可能每次都全部排序然后得到最大的 K 个,否则肯定超时。因此,必须要维护一个长度最大为 K 的 vector,用来保存 K个最大的 query。然后分三种情况:①当前输入id 不在 v内,v的长度小于K,直接加入v。② 当前id在v内,v的长度等于K, 比较当前id和v中最小元素的大小,决定是否要增删。③ 当前id在v内,更新当前id对应的计数值。最后,对v排序。由于v的长度不超过10,即使进行50000次排序,也不会超时。设置hashTable用于记录id是否在v中。
AC代码:
#include <vector>
#include <algorithm>
#include <cstdio>
using namespace std;
struct query
{
int cnt;
int index;
bool operator <(const query &other)
{
if(this->cnt != other.cnt) return this->cnt > other.cnt;
else return this->index < other.index;
}
};
int main()
{
int N, K;
scanf("%d%d", &N, &K);
vector<bool> inq(N+1, 0);
vector<int> cnt(N+1, 0);
vector<query> v;
for (int i = 0; i < N; ++i)
{
query now;
scanf("%d", &now.index);
now.cnt = ++cnt[now.index];
if(i > 0)
{
printf("%d:", now.index);
for (int j = 0; j < v.size(); ++j)
printf(" %d", v[j].index);
printf("\n");
}
if(!inq[now.index] && v.size() < K)
{
v.push_back(now);
inq[now.index] = true;
}
else if(!inq[now.index] && v.size() == K)
{
if(now.cnt > v[K-1].cnt || (now.cnt == v[K-1].cnt && now.index < v[K-1].index))
{
inq[v[K-1].index] = false;
v.pop_back();
v.push_back(now);
inq[now.index] = true;
}
}
else if(inq[now.index])
{
for (int j = 0; j < v.size(); ++j)
if(v[j].index == now.index) v[j] = now;
}
sort(v.begin(), v.end());
}
return 0;
}
事实上一开始没有想到用vector,而是想用优先队列来实现,维护一个最大长度为K的优先队列q,队首始终是最小的那个元素。思想基本上一样,分三种情况,①当前输入不在q内,q的长度小于K,那么加入。② 当前输入不在q内,q的长度等于K,那么比较当前输入和队首元素的关系,决定是否要增删。③ 当前输入在q内,那么更新q的内容。
但由于优先队列不能直接操作元素,只能不断pop,所以代码写起来更冗长。同时注意优先队列重载小于运算符要写成全局函数,否则无法编译。
优先队列AC代码:
#include <vector>
#include <cstdio>
#include <queue>
using namespace std;
struct query
{
int cnt;
int index;
};
bool operator<(query a, query b)
{
if(a.cnt != b.cnt) return a.cnt > b.cnt;
else return a.index < b.index;
}
int main()
{
int N, K;
scanf("%d%d", &N, &K);
vector<bool> inq(N+1, 0);
vector<int> cnt(N+1, 0);
priority_queue<query> q;
for (int i = 0; i < N; ++i)
{
query now;
scanf("%d", &now.index);
now.cnt = ++cnt[now.index];
if(i > 0)
{
printf("%d:", now.index);
priority_queue<query> tmp = q;
vector<int> v;
while(!tmp.empty())
{
query t = tmp.top();
tmp.pop();
v.push_back(t.index);
}
for (int j = v.size() - 1; j >= 0; --j)
printf(" %d", v[j]);
printf("\n");
}
if(!inq[now.index] && q.size() < K)
{
q.push(now);
inq[now.index] = true;
}
else if(!inq[now.index] && q.size() == K)
{
query t = q.top();
if(now.cnt > t.cnt || (now.cnt == t.cnt && now.index < t.index))
{
q.pop();
inq[t.index] = false;
q.push(now);
inq[now.index] = true;
}
}
else if(inq[now.index])
{
priority_queue<query> tmp;
while(!q.empty())
{
query t = q.top();
q.pop();
if(t.index != now.index) tmp.push(t);
}
tmp.push(now);
q = tmp;
}
}
return 0;
}