poj 1456 Supermarket(并查集维护区间)

时间:2023-03-08 15:28:06
poj 1456 Supermarket(并查集维护区间)


题意:有一些货物,每一个货物有价值和卖出的截至日期,每天能够卖一个货物,问能卖出的最大价值是多少。

思路:算法不难想到,按价值降序排列。对于每一件货物,从deadline那天開始考虑。假设哪天空暇那么将货物在该天卖出。

假设直接暴力来做。复杂度为o(n*n),显然不行。能够用并查集来维护当前ddl之前空暇的近期的一天,假设父节点为0说明deadline之前没有空暇的时间,那么该货物就无法卖出。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#define eps 1e-6
#define LL long long
using namespace std; const int maxn = 10000 + 100;
const int INF = 0x3f3f3f3f;
int pre[maxn];
int n;
struct Prod {
int val, ddl;
bool operator < (const Prod& A) const { return val > A.val;}
} prod[maxn]; int find(int x) {
if(x == pre[x]) return x;
return pre[x] = find(pre[x]);
} void init() {
for(int i = 1; i < 10005; i++) pre[i] = i;
for(int i = 0; i < n; i++) cin >> prod[i].val >> prod[i].ddl;
} void solve() {
int ans = 0;
sort(prod, prod+n);
for(int i = 0; i < n; i++) {
if(find(prod[i].ddl)) {
ans += prod[i].val;
pre[pre[prod[i].ddl]] = find(pre[prod[i].ddl]-1);
}
}
cout << ans << endl;
} int main() {
//freopen("input.txt", "r", stdin);
while(scanf("%d", &n) == 1) {
init();
solve();
}
return 0;
}