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;
}











原文地址:https://www.cnblogs.com/mengfanrong/p/5071108.html