title
POJ 3017
AcWing 299
Description
Given an integer sequence of length , you are to cut the sequence into several parts every one of which is a consecutive subsequence of the original sequence. Every part must satisfy that the sum of the integers in the part is not greater than a given integer . You are to find a cutting that minimizes the sum of the maximum integer of each part.
Input
The first line of input contains two integer . The following line contains N integers describes the integer sequence. Every integer in the sequence is between 0 and 1 000 000 inclusively.
Output
Output one integer which is the minimum sum of the maximum integer of each part. If no such cuttings exist, output −1.
Sample Input
8 17
2 2 2 8 1 8 2 1
Sample Output
12
Hint
Use 64-bit integer type to hold M.
Source
POJ Monthly–2006.09.29, zhucheng
analysis
设
为前
个数取得的最小和,那么我们可以有递推公式:
由于
,那么可以发现
必然是非递减的。
设 中的最大值下标为 ,
由 的非递减性, 。
所以我们取 ,也就是说如果某一段到当前位置 的最大值都一样,取最靠前的即可。
那么可以联想到单调队列,维护一个递减的队列,存的是符合要求的某一段的最大值。
但是需要注意!
队首元素不一定是最优的,由于队列的递减性质,队列中的所有元素都有可能组成最优解。
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
template<typename T>inline void read(T &x)
{
x=0;
T f=1, ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
struct Orz{ll val; int id;}q[maxn];
ll f[maxn];
int a[maxn];
int main()
{
int n; ll m;
while (~scanf("%d %lld",&n,&m))
{
bool flag=1;
for (int i=1; i<=n; ++i)
{
read(a[i]);
if (a[i]>m) flag=0;
}
if (!flag) { puts("-1"); continue; }
int l=0,r=0,pos=1;
ll sum=a[1];
q[r].val=f[1]=a[1], q[r++].id=1;
for (int i=2; i<=n; ++i)
{
sum+=a[i];
while (sum>m && pos<i) sum-=a[pos],++pos;
while (l<r && q[r-1].val<=a[i]) --r;
q[r].val=a[i], q[r++].id=i;
while (l<r && q[l].id<pos) ++l;
f[i]=f[pos-1]+q[l].val;
for (int j=l; j<r-1; ++j) f[i]=min(f[i],f[q[j].id]+q[j+1].val);
}
printf("%lld\n",f[n]);
}
return 0;
}