题意:
给出一些事件的开始时间和持续时间,你必须在开始时间前做这件事,做完才能做别的,每件事有固定的报酬,询问怎么安排报酬最大。
题解:
可以写出DP方程:
这里的mmax表示这个事件开始时间之前所能达到的最大报酬。
dp[ed]=max(dp[ed],mmax+Node[i].w);
然后从1到N做一遍DP即可,这里前缀最大值需要用一个树状数组维护,但是不用好像也能过。。。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=3e6+100; struct node { ll st; ll ed; ll w; }Node[maxn]; ll dp[maxn]; ll c[maxn]; ll E=0; int cmp (node a,node b) { if (a.st!=b.st) return a.st<b.st; else return a.ed<b.ed; } int lowbit (int x) { return x&-x; } ll getsum (int x) { ll ans=0; for (int i=x;i;i-=lowbit(i)) ans=max(ans,c[i]); return ans; } void update (int t,ll x) { for (int i=t;i<=E;i+=lowbit(i)) c[i]=max(c[i],x); } int main () { int N; scanf("%d",&N); for (int i=1;i<=N;i++) { ll x; scanf("%lld%lld%lld",&Node[i].st,&Node[i].w,&x); Node[i].ed=Node[i].st+x; E=max(E,Node[i].ed); } sort(Node+1,Node+1+N,cmp); for (int i=1;i<=N;i++) { ll st=Node[i].st; ll ed=Node[i].ed; ll mmax=getsum(st); dp[ed]=max(dp[ed],mmax+Node[i].w); update(ed,dp[ed]); } ll Max=0; for (int i=0;i<=E;i++) Max=max(Max,dp[i]); printf("%lld ",Max); }