1129 Recommendation System + 大顶堆 + 结构体小于号重载
刷题时经常会遇到,可以把问题抽象成维护一个有序数组的任务。这个时候大顶堆就是一个不错的选择。其实C++ STL中的set
OJ题目链接:https://oj.haizeix.com/problem/285
题解代码:
#include<iostream>
#include<set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX_M 2000
int a[MAX_M + 5];
typedef pair<int, int> PII;
set<PII> s;
int t = 0; // 时间戳,去重
int n, m, x;
void extract() {
for (int j = m - 1; j >= 0; j--) {
a[j] = -(s.begin()->first);
s.erase(s.begin());
}
}
int main() {
cin >> n >> m;
for (int i = 0; i < m; i++) {
cin >> x;
s.insert(PII(-x, t++));
}
for (int i = 1; i < n; i++) {
extract(); // 这个是第一层的所有元素跟第二层的所有元素配对完以后剩下的大顶堆中的元素作为一二两层元素的代表前往第三层匹配。以此类推,不断合并。
for (int i = 0; i < m; i++) s.insert(PII(-inf, t++)); // set内部维护有序性的时候是依据pair中的first元素来的
for (int j = 0; j < m; j++) {
cin >> x;
for (int k = 0; k < m; k++) {
int y = x + a[k];
if (y >= -(s.begin()->first)) break;
s.erase(s.begin());
s.insert(PII(-y, t++));
}
}
}
extract();
for (int i = 0; i < m; i++) {
i && cout << " ";
cout << a[i];
}
cout << endl;
return 0;
}
或者当我们需要维护自定义数据结构的有序性的时候,可以重载一下“<”号。
PAT题目链接:https://pintia.cn/problem-sets/994805342720868352/exam/problems/994805348471259136
题解代码:
#include<iostream>
#include<set>
using namespace std;
int a[50005];
struct node {
int value, cnt;
node(int a, int b) : value(a), cnt(b) {}
bool operator < (const node &a) const {
return (cnt != a.cnt) ? cnt > a.cnt : value < a.value;
}
};
set<node> s;
int main() {
int n, k, num;
scanf("%d%d", &n, &k);
for(int i = 0; i < n; i++) {
scanf("%d", &num);
if (i) {
printf("%d:", num);
int j = 0;
for (auto iter = s.begin(); iter != s.end() && j < k; iter++, j++) {
printf(" %d", iter->value);
}
printf("\n");
}
// 维护大顶堆
auto it = s.find(node(num, a[num]));
if (it != s.end()) s.erase(it);
a[num]++;
s.insert(node(num, a[num]));
}
return 0;
}
PAT题目链接:https://pintia.cn/problem-sets/994805342720868352/exam/problems/1478634991737962496
题解代码:
#include<iostream>
#include<vector>
#include<string>
#include<set>
#include<unordered_map>
using namespace std;
#define MAX_N 100000
struct node {
string id;
int y, m, d;
node (string id, int y, int m, int d) : id(id), y(y), m(m), d(d) {}
// 年纪最大的排最前面
bool operator < (const node &a) const {
return (y != a.y) ? y < a.y : (m != a.m ? m < a.m : d < a.d);
}
};
int cnt;
set<node> s, all;
vector<node> v;
unordered_map<string, int> M;
void extact(string id) {
int year = stoi(id.substr(7,4));
int month = stoi(id.substr(11,2));
int day = stoi(id.substr(13,2));
M[id] = cnt++;
v.push_back(node(id, year, month, day));
all.insert(v[M[id]]);
}
int main() {
int n, m;
string id;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> id;
extact(id);
}
cin >> m;
for (int i = 0 ; i < m; i++) {
cin >> id;
if (M.find(id) != M.end()) {
s.insert(v[M[id]]);
} else {
extact(id);
}
}
if (s.size()) {
cout << s.size() << endl;
cout << s.begin()->id << endl;
} else {
cout << 0 << endl;
cout << all.begin()->id << endl;
}
return 0;
}

浙公网安备 33010602011771号