题目链接
http://poj.org/problem?id=1456
分析
除了堆可以来实现贪心做法,并查集也可行;
先将商品按利润不增排序,依次考虑每件商品,尽量将其放在不过期且靠后时卖出;
用并查集来维护每天及此前最靠后的空闲位置,每选定一天,则将其加入到其前一天所在集合。
AC代码
#include <cstdio>
#include <algorithm>
using namespace std;
inline int read() {
int num = 0;
char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9')
num = num * 10 + c - '0', c = getchar();
return num;
}
const int maxn = 1e4 + 5, maxd = 1e4;
struct Product {
int p, d;
bool operator < (const Product& rhs) const {
return p > rhs.p;
}
} pro[maxn];
int n, f[maxn];
int find(int x) {
if (x == f[x]) return x;
return f[x] = find(f[x]);
}
inline void merge(int a, int b) {
a = find(a), b = find(b);
if (a != b) f[a] = b;
}
int main() {
while (scanf("%d", &n) == 1) {
for (int i = 1; i <= maxd; ++i) f[i] = i;
for (int i = 1; i <= n; ++i) pro[i].p = read(), pro[i].d = read();
sort(pro + 1, pro + n + 1);
int ans = 0;
for (int i = 1; i <= n; ++i) {
int r = find(pro[i].d);
if (!r) continue;
ans += pro[i].p, merge(r, r - 1);
}
printf("%d\n", ans);
}
return 0;
}