POJ 3017|Cut the Sequence|动态规划|单调队列

给定一个数列 {an} ,任意将连续的 ai 分块,使所有块的和都不超过 M ,最小化各块的最大值的和。

dp[i]=min{dp[j]+max{a[j..i1]}}

其中 i1k=jakM
时间复杂度是 O(n2) ,通过打表我们可以发现决策单调性(误),由于 dp[i] 是单调增的, ak 的最大值也是单调不降的,而且还得满足和不大于M,因此 j 是不减的,考虑单调队列。
开一个单调队列,使得队首到当前位置的和不超过m,那么单调队列里随便哪个元素都是满足要求的:
dp[i]=min{dp[q[j]]+a[q[j+1]]}

对于单调队列的最小值,set维护即可。

#include <cstdio>
#include <set>
using namespace std;
typedef long long ll;
const int N = 100005;
int q[N], dp[N], a[N];
multiset<int> s;
ll calc(int n, ll m) {
    int i, j = 1, k, f = 0, r = 0; ll sum = 0;
    for (i = 1; i <= n; ++i) {
        sum += a[i];
        while (sum > m) sum -= a[j++];
        if (j > i) return -1;
        while (f < r && a[q[r - 1]] <= a[i]) {
            if (r - f >= 2) s.erase(dp[q[r - 2]] + a[q[r - 1]]);
            --r;
        }
        q[r++] = i; if (r - f >= 2) s.insert(dp[q[r - 2]] + a[q[r - 1]]);
        while (f < r && q[f] < j) {
            if (r - f >= 2) s.erase(dp[q[f]] + a[q[f + 1]]);
            ++f;
        }
        dp[i] = dp[j - 1] + a[q[f]];
        if (r - f >= 2) dp[i] = min(dp[i], *s.begin());
    }
    return dp[n];
}
int main() {
    int i, n; ll m;
    scanf("%d%lld", &n, &m);
    for (i = 1; i <= n; ++i) scanf("%d", &a[i]);
    return printf("%lld", calc(n, m)), 0;
}

Cut the Sequence

Time Limit: 2000MS Memory Limit: 131072K
Total Submissions: 9998 Accepted: 2999

Description

Given an integer sequence { an } of length N, 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 M. 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 N (0 < N ≤ 100 000), M. 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值