Poj 3017 cut the sequence (monotonous queue optimization DP)
ACM
Question address:
Poj 3017 cut the sequence
Question:
Divide a sequence composed of N numbers into several segments. The sum of numbers in each segment must not exceed M and the minimum division method of the sum of the maximum values in each segment is obtained, output the smallest sum.
Analysis:
The equation is: DP [I] = min (DP [J] + maxsum [J + 1] [I])
However, N * n is too complex and needs optimization.
You can use the monotonous queue + BST optimization, but you only need to maintain the maximum value of each segment.
I have read the answer to this question: http://blog.csdn.net/muye67/article/details/5999033.
Code:
/** Author: illuz <iilluzen[at]gmail.com>* File: 3017.cpp* Create Date: 2014-09-17 21:41:41* Descripton: dp */#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define repf(i,a,b) for(int i=(a);i<=(b);i++)typedef long long ll;const int N = 1e5+10;ll n, m, arr[N], sum[N];ll dp[N], q[N];int front, rear;int main() {ios_base::sync_with_stdio(0);while (cin >> n >> m) {sum[0] = 0;repf (i, 1, n) {cin >> arr[i];sum[i] = sum[i - 1] + arr[i];}front = rear = 1;q[rear] = 1;bool flag = arr[1] > m;int t = 0;dp[0] = 0;dp[1] = arr[1];repf (i, 2, n) {while (i > t && sum[i] - sum[t] > m)t++;if (i == t) {flag = 1;break;}while (front <= rear && arr[i] >= arr[q[rear]])rear--;q[++rear] = i;while (front <= rear && sum[i] - sum[q[front] - 1] > m)front++;dp[i] = dp[t] + arr[q[front]];repf (j, front, rear - 1)dp[i] = min(dp[i], dp[q[j]] + arr[q[j + 1]]);}cout << (flag ? -1 : dp[n]) << endl;}return 0;}
Poj 3017 cut the sequence (monotonous queue optimization DP)