surf(树状数组+DP)

题意:

给出一些事件的开始时间和持续时间,你必须在开始时间前做这件事,做完才能做别的,每件事有固定的报酬,询问怎么安排报酬最大。

题解:

可以写出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);
}
原文地址:https://www.cnblogs.com/zhanglichen/p/12898133.html