[TJOI2011] 书架

#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
using namespace std;
struct dat
{int val,wei,ff;};
dat line[100005];
int tre[500005],book[100005],qian[100005],f[100005],n,m,h,t,head,tail,s,p,ma;
void jia(int wei,int val,int l,int r,int root)
{
    if (l==r){tre[root]=val;return;}
    int mid=(l+r)/2;
    if (wei<=mid)jia(wei,val,l,mid,root*2);
    else jia(wei,val,mid+1,r,root*2+1);
    tre[root]=min(tre[root*2],tre[root*2+1]);
}
int fid(int h,int t,int l,int r,int root)
{
    if (l==r){return tre[root];}
    if (h<=l && t>=r)return tre[root];
    int mid=(l+r)/2,mm=1000000007;
    if (h<=mid)mm=fid(h,t,l,mid,root*2);
    if (t>=mid+1) mm=min(mm,fid(h,t,mid+1,r,root*2+1));
    return mm;
}
int main()
{
    cin>>n>>m;
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&book[i]);
    }
    h=1;head=1;tail=0;
    while (t<n && s+book[t+1]<=m)
    {
         t++;s+=book[t];qian[t]=1;ma=max(ma,book[t]);f[t]=ma;
         while (tail>0 && book[t]>=line[tail].val)tail--;
         tail++;line[tail].val=book[t];line[tail].wei=t;line[tail].ff=line[tail-1].wei;
         jia(tail,f[line[tail-1].wei]+book[t],1,n,1);
    }
    for (int i=t+1;i<=n;i++)
    {
        s+=book[i];
        while (s>m){s-=book[h];h++;}
        qian[i]=h;
    }
     for (int i=t+1;i<=n;i++)
     {
         while (line[head].wei<qian[i] && head<=tail){line[head].wei=0;head++;}
         if (line[head].ff<qian[i]-1){line[head].ff=qian[i]-1;jia(head,f[qian[i]-1]+line[head].val,1,n,1);}
         while (tail>=head && book[i]>=line[tail].val){tail--;}
         tail++;line[tail].val=book[i];line[tail].wei=i;line[tail].ff=max(line[tail-1].wei,qian[i]-1);
         jia(tail,f[line[tail].ff]+book[i],1,n,1);
         f[i]=fid(head,tail,1,n,1);
     }
     cout<<f[n];
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值