蓝书(算法竞赛进阶指南)刷题记录——POJ1456 Supermarket(贪心+并查集)

题目:POJ1456.
题目大意:给定 n n n个物品,其中第 i i i个价值为 v i v_i vi,并且要在时间点 t i t_i ti之前卖出才有 v i v_i vi的价值.现在每天只能买一个物品,求最大价值和.
1 ≤ n , v i , t i ≤ 1 0 4 1\leq n,v_i,t_i\leq 10^4 1n,vi,ti104.

很容易想到一个贪心策略,先按照价值从大到小排序,然后依次放入.对于每个物品 i i i,若 t i t_i ti前还有没有被占领的时间点就放到这之中最迟的时间点上,否则就抛弃这个物品.

发现这个算法是 O ( n 2 ) O(n^2) O(n2)的,考虑优化.

考虑使用并查集,把每一个时间点看成一个点,每个点的祖先就是在这个时间点之前最迟的空位,这样就可以做到 O ( n log ⁡ n ) O(n\log n) O(nlogn)解决此题了.

代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
  using namespace std;

#define Abigail inline void
typedef long long LL;

const int N=10000;

struct thing{
  int t,v;
  bool operator < (const thing &p)const{return v<p.v;}
}a[N+9];
int n,mx,fa[N+9],sum;

int get(int u){return u^fa[u]?fa[u]=get(fa[u]):u;}

Abigail into(){
  for (int i=1;i<=n;++i){
    scanf("%d%d",&a[i].v,&a[i].t);
    mx=max(mx,a[i].t);
  }
}

Abigail work(){
  sort(a+1,a+1+n);
  for (int i=0;i<=mx;++i) fa[i]=i;
  int u;
  sum=0;
  for (int i=n;i>=1;--i){
  	u=get(a[i].t);
	if (!u) continue;
  	sum+=a[i].v;
  	fa[u]=get(u-1);
  }
}

Abigail outo(){
  printf("%d\n",sum);
}

int main(){
  while (~scanf("%d",&n)){
    into();
    work();
    outo(); 
  }
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值