洛谷2889 [USACO07NOV]挤奶的时间Milking Time(DP)(树状数组)

版权声明:本文为博主原创文章,未经博主允许不得转载,除非先点了赞。 https://blog.csdn.net/A_Bright_CH/article/details/83108520

题意

奶牛Bessie在0~N时间段产奶。农夫约翰有M个时间段可以挤奶,时间段f,t内Bessie能挤到的牛奶量e。奶牛产奶后需要休息R小时才能继续下一次产奶,求Bessie最大的挤奶量。
如果在(si,ti)时刻挤奶,那么休息完的时间是si+r,即下一次可以挤奶的最早时间是(si+r,...)。

题解

DP+树状数组
设f[i]表示在第i小时结束挤奶时收获的最大奶量。有如下DP方程
f[i]=\max_{0<=j<=i-r}\left\{f[j]\right\}
可以用树状数组解决这个问题。真高兴,第一道自己YY出来的树状数组优化DP,尽管很水。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1000010,maxm=1010;

int n,m,r,ans=0;

struct U{int s,t,c;}a[maxm];
bool cmp(U u1,U u2){return u1.s<u2.s;}

int mx[maxn];
void change(int x,int c)
{
    for(;x<=n;x+=x&-x) mx[x]=max(mx[x],c);
}
int findmax(int x)
{
    int re=-(1<<30);
    for(;x>=1;x-=x&-x) re=max(re,mx[x]);
    return re;
}

int main()
{
    scanf("%d%d%d",&n,&m,&r);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&a[i].s,&a[i].t,&a[i].c);
        a[i].s++;a[i].t++;
    }n++;
    sort(a+1,a+m+1,cmp);
    for(int i=1;i<=m;i++)
    {
        int f=findmax(max(a[i].s-r,1))+a[i].c;
        ans=max(ans,f);
        change(a[i].t,f);
    }
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/A_Bright_CH/article/details/83108520