poj 3616 Milking Time dp+树状数组

题意:

给一堆区间,每个区间有开始时间s,结束时间e,和收益w,现在要找一些区间使收益和最大,且区间之间的间隔最小为r。

分析:

这道题用dp做是简单题,用dp+树状数组做是中等题。dp问题的关键是对状态的定义。有两种方法,一:dp[k]表示按开始时间排序到第k个区间能取得的最大收益。二:dp[t]表示在时间t时能获得的最大收益。定义好状态方程就好写了这不再赘述。有趣的是这个时间复杂度。设一共有M个区间,所有区间的最大时间为L,第一种是M^2的,第二种是M*(logL+logM)的,这题M才1000两种都能过,第一种比较好写所以我写的是第二种,用到了树状数组,树状数组本来是求动态区间和的,但这题区间左端恒为1所以也可以用树状数组来做rmq。

代码:

//poj 3616
//sep9
#include <iostream>
#include <algorithm>
using namespace std;
const int maxN=1000024;
const int maxM=1024;
int dp[maxN];
struct Node
{
	int s,e,w;
}interval[maxM];

int cmp(Node a,Node b)
{
	return a.e<b.e;
}

struct BIT
{
	int c[maxN],n;
	BIT(){}
	void clear(){
		memset(c,0,sizeof(c));
	}
	int lowbit(int x)
	{
		return x&(x^(x-1));
	}
	void modify(int i,int d)
	{
		while(i<=n){
			c[i]=max(c[i],d);
			i+=lowbit(i);
		}
	}
	int q(int i)
	{
		int sum;
		for(sum=0;i>0;i-=lowbit(i))
			sum=max(sum,c[i]);
		return sum;
	}
}bit;
int main()
{
	int i,n,m,r;
	memset(dp,0,sizeof(dp));
	scanf("%d%d%d",&n,&m,&r);
	bit.n=n;
	for(i=0;i<m;++i)
		scanf("%d%d%d",&interval[i].s,&interval[i].e,&interval[i].w);
	sort(interval,interval+m,cmp);
	for(i=0;i<m;++i){
		int s=interval[i].s,e=interval[i].e,w=interval[i].w;
		dp[e]=w;
		if(s-r>0)
			dp[e]=max(dp[e],bit.q(s-r)+w);
		bit.modify(e,dp[e]);
	}	
	int ans=0;
 	for(i=0;i<m;++i)
		ans=max(ans,dp[interval[i].e]);
	printf("%d",ans);
	return 0;	
} 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值