题意:
给一堆区间,每个区间有开始时间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; }
时间: 2024-10-27 05:09:04