题目描述
由于最近又购买了很多书,所以你打算在自己的书房做一个新书架,但是由于墙体高度有限,并且为了照顾整体效果,你希望你的书架的宽度越小越好,所谓宽度就是指书架在垂直方向上占据的距离。
现按一定顺序给出所有要放置于书架上的书,要求求书架的最小宽度。每本书都有一个长度,而书架是「目」字形的,一层的宽度不能小于其上所摆放的任何一本书的长度。每本书的重量和它的长度成正比,而每层书架都有同样的最大承重,简单起见,换算成长度单位,记为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 |
#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;
}