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;
}
时间: 2024-10-25 04:34:58

poj 1456 Supermarket(并查集维护区间)的相关文章

poj 1456 Supermarket - 并查集 - 贪心

题目传送门 传送点I 传送点II 题目大意 有$n$个商品可以销售.每个商品销售会获得一个利润,但也有一个时间限制.每个商品需要1天的时间销售,一天也只能销售一件商品.问最大获利. 考虑将出售每个物品尽量外后安排.这样当一个商品不能安排的时候看能不能替换掉它能够出售的时间中盈利最小的商品. 因此可以将物品排序,这样只用考虑能否让每个物品出售. 为了找到第一个空闲时间,又因为已经安排的时间不会改变,所以用并查集将已经安排了出售的时间段缩起来. Code 1 /** 2 * poj 3 * Prob

Supermarket poj 1456 贪心+并查集优化

Language: Default Supermarket Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9512   Accepted: 4096 Description A supermarket has a set Prod of products on sale. It earns a profit px for each product x∈Prod sold by a deadline dx that is

POJ 1456 (贪心+并查集) Supermarket

有n件商品,每件商品有它的利润和售出的最后期限,问能够得到的最大利润是多少 这道题和 HDU 1789 Doing Homework again 几乎一模一样,只不过这个是求最的扣分,本题是求最大利润 朴素的做法是: 按照每件商品的利润从大到小排序,有一个busy数组记录那天是否有东西卖出.对于每件商品,从它的截止日期开始遍历,如果那天有东西卖就看看前一天是否有卖东西,直到有一天没有东西卖或者前面的天数都有卖的. 1 //#define LOCAL 2 #include <iostream>

POJ 1456 贪心 并查集

看一下中文版的题目就好,英文题目太晦涩了. 有两种方法可以解题 一种是贪心+优先队列 另一种是贪心+并查集 优先队列  需要说的都在代码注释里 #include<cstdio> #include<queue> #include<algorithm> using namespace std; struct s{ int day, val; }arr[100005]; bool cmp(s a, s b){ if(a.day != b.day) return a.day &

poj 1456 Supermarket (贪心+并查集)

# include <stdio.h> # include <algorithm> # include <string.h> using namespace std; int fa[10010]; struct node { int p; int d; }; struct node a[10010]; bool cmp(node a1,node a2)//利润从大到小 { return a1.p>a2.p; } int find(int x) { if(fa[x]

POJ - Colored Sticks - 并查集+字典树

这道题主要还是要判断是不是欧拉图 说白了就是能不能这幅图能不能用一笔画下来,那么就可以知道了,如果是一个环状的,说明奇数度就不存在,否则就只能用两个奇数度(起点终点)//我的理解这是 只需要用字典树将单词变为对应的一个数字,然后并查集操作就可以,需要维护一个度变量 #include<stdio.h> #include<string.h> int du[500010],p[500010]; int tot=1; struct tree { tree *next[30]; int id

POJ 2492 (简单并查集) A Bug&#39;s Life

题意:有编号为1~n的虫子,开始假设这种昆虫是异性恋.然后已知xi 和 yi进行交配,根据已知情况分析能否推理出其中是否有同性恋 这道题和 POJ 1182 食物链 十分相似,不过在更新与父节点关系的时候要简单一些 sex数组保存的是与父节点的性别关系,如果与父节点是同性,则为0,否则是1 每次路径压缩的同时要更新sex[a] = (sex[a] + sex[temp]) % 2; 还有就是如果x 和 y 不在一个集合,两棵树进行合并的时候,考虑x px y py 四者之间的关系,有 paren

poj 2513 欧拉回路+并查集判断是否联通+Trie树

http://poj.org/problem?id=2513 最初看到 第一感觉---map  一看250000的数据量 果断放弃 然后记得以前看过,trie代替map,尤其当数据量特别大的时候 学到了: 1.Trie代替map的思想,可以在单词结尾的tree[i][tk]  这个i作为字符串对应的int值 ,当然这个int值也可以用于建立并查集 2.接上,通过并查集判断,所有的点在同一个集合图就是联通的,否则不联通,注意tree[i][tk]>0 表示是单词结尾, x=Find(x);//这句

[Codeforces 1027 F] Session in BSU [并查集维护二分图匹配问题]

题面 传送门 思路 真是一道神奇的题目呢 题目本身可以转化为二分图匹配问题,要求右半部分选择的点的最大编号最小的一组完美匹配 注意到这里左边半部分有一个性质:每个点恰好连出两条边到右半部分 那么我们可以利用这个性质 考虑一个左边的点和它右边联通的两个点,发现这两个点只能选择一个和这个左边的点匹配 那么我们考虑把这个点点匹配的模型转化成点边匹配 我们在同一个左边点连的两个右边点之间连边,那么问题就变成了一个点和一条相邻的边匹配,求完美匹配的问题了 而这个问题,我们显然可以用并查集来很好的解决 考虑