欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

书架

程序员文章站 2022-05-09 13:47:12
...

题目描述

由于最近又购买了很多书,所以你打算在自己的书房做一个新书架,但是由于墙体高度有限,并且为了照顾整体效果,你希望你的书架的宽度越小越好,所谓宽度就是指书架在垂直方向上占据的距离。

现按一定顺序给出所有要放置于书架上的书,要求求书架的最小宽度。每本书都有一个长度,而书架是「目」字形的,一层的宽度不能小于其上所摆放的任何一本书的长度。每本书的重量和它的长度成正比,而每层书架都有同样的最大承重,简单起见,换算成长度单位,记为m,也就是说每层上的书的长度之和不得超过m。整个书架的宽度为其上所有层的宽度之和。为了便于查找,任何层上的书必须为给出的书中的连续几本。

输入输出格式

输入格式:
第一行有两个正整数n、m。接下来有n行,每行一个正整数hi,i从1到n,hi ≤ m。

输出格式:
共一行,一个整数表示书架的最小宽度。

输入输出样例
输入样例#1: 复制
4 6
1
3
3
1
输出样例#1: 复制
5

说明
对于30%的数据,n ≤ 1,000
对于100%的数据,n ≤ 100,000,hi ≤ 10,000,m ≤ 1,000,000,000

成果(exe)
题解:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define imin(a,b) ((a<b)?(a):(b))
#define imax(a,b) ((a>b)?(a):(b))
using namespace std;
typedef long long ll;
const int N=100100;
const ll inf=1e9;
const int mp=17;
int n,m;
int d[N],la[N];
int l,r;
ll sum[N],f[N],qx[N<<1],qy[N<<1];
ll h1[N],h2[N];
int cnt1,cnt2;
void add1(ll x) {
    cnt1++; h1[cnt1]=x;    int now=cnt1;
    while((now>1) && (h1[now>>1]>h1[now])) { swap(h1[now>>1],h1[now]); now>>=1;    }}
void down1() {
    h1[1]=h1[cnt1]; cnt1--;    int now=1;
    while((now<<1)<=cnt1) {
        int uw;    if((now<<1|1)>cnt1) uw=now<<1; else uw=(h1[now<<1]<h1[now<<1|1])?(now<<1):(now<<1|1);
        if(h1[now]>h1[uw]) swap(h1[now],h1[uw]); else break; now=uw; }}
void add2(int x) {
    cnt2++; h2[cnt2]=x;    int now=cnt2;
    while((now>1) && (h2[now>>1]>h2[now])) { swap(h2[now>>1],h2[now]); now>>=1; }}
void down2() {
    h2[1]=h2[cnt2]; cnt2--;    int now=1;
    while((now<<1)<=cnt2) {
        int uw; if((now<<1|1)>cnt2) uw=now<<1; else uw=(h2[now<<1]<h2[now<<1|1])?(now<<1):(now<<1|1);
        if(h2[now]>h2[uw]) swap(h2[now],h2[uw]); else break; now=uw; }}
ll getans()
{
    while(cnt2 && h1[1]==h2[1]) down1(),down2();
    return h1[1];
}
void read(int &x)
{
    x=0; char ch=getchar();
    while(ch<'0' && ch>'9') ch=getchar();
    while(ch>='0' && ch<='9')
    {
        x=(x<<3)+(x<<1)+ch-'0';
        ch=getchar();
    }
}
int main()
{
    read(n); read(m); sum[0]=0ll;
    for(int i=1;i<=n;i++) read(d[i]),sum[i]=sum[i-1]+d[i];
    int la=1; l=N; r=N-1;
    for(int i=1;i<=n;i++)
    {
        while(sum[i]-sum[la-1]>m)
        {
            if(r>=l && qx[l]==la) add2(f[la-1]+qy[l]),l++;
            la++;
        }
        if(l>r || qx[l]!=la)
        {
            l--;
            if(la==i) qy[l]=d[i];
            else qy[l]=imax(qy[l],d[i]);
            qx[l]=la;
            add1(f[la-1]+qy[l]);
        }
        int p=i;
        while(r>=l && qy[r]<=d[i])
        {
            p=qx[r];
            add2(f[qx[r]-1]+qy[r]);
            r--;
        }
        qx[++r]=p; qy[r]=d[i];
        add1(f[p-1]+d[i]);
        f[i]=getans();
    }
    printf("%lld\n",f[n]);
    return 0;
}
相关标签: 洛谷