算法1:数组维护前k个商品编号() $O(NKlogK)$
//只排序前k个商品编号,统计每个商品访问次数,50000 * 10 * 3 操作*排序
#include <bits/stdc++.h>
using namespace std;
const int N = 5E4+10;
int cnt[N], a[14], n, m;
int main() {
scanf("%d%d", &n, &m);
int k = 0;
for (int i = 0, id; i < n; ++ i) {
scanf("%d", &id);
if (i) {
printf("%d: ", id);
for (int j = 0; j < k; ++ j) printf("%d ", a[j]);
printf("\n");
}
cnt[id]++;
bool f = 1; //查看一下id是否已经在a数组中, 默认不在,需要加进去
for (int j = 0; j < k; ++ j)
if (a[j] == id)
f = 0;
if (f) a[k++] = id; //k记录数量
sort(a, a+k, [](int x, int y){ //匿名函数-lambda表达式
if (cnt[x] != cnt[y]) return cnt[x] > cnt[y];
return x < y;
});
k = min(k, m); //最多m个,k当前实际有的
}
return 0;
}
算法2:set-map维护() $O(nlogm)$
//set维护次数-商品,次数负数表示,map正常存储商品-次数;次数更新时,set要删除
//常数比较大
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
set<PII> s; //默认是升序排序,小的在前,
map<int, int> cnt;
int n, m;
int main() {
scanf("%d%d", &n, &m);
for (int i = 0, id; i < n; ++ i) {
scanf("%d", &id);
if (i) {
printf("%d: ", id);
int j = 0;
for (auto item : s) {
if (++j > m) break;
printf("%d ", item.second);
}
printf("\n");
}
if (!cnt[id]) { //没有出现,就加入进去
cnt[id] = 1;
s.insert({-1, id});
} else {
s.erase({-cnt[id], id}); //删除原有的次数
cnt[id] = cnt[id] + 1;
s.insert({-cnt[id], id}); //重新插入
}
}
return 0;
}