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.
题目意思就是,给你一段数列,分成几个部分,要使每个部分的最大值的和最小,呵呵,听起来有点绕!
壮态转移方程f[i]=f[j]+max[j,r];但这题f[j]+max[j,r]可以用优先队列来存,其实要注意,优先队列,到底是存的是什么,优先队列,不能存入的是与现在状态改变,就变的值,你想如果这个值与i有关的话,当然要提出来,这是刚作单调队列的时候,有个小误区,当然这是后话,到时候,再分析,这还是很水的题啊!但这样,因为队首不是最优解,所以还是n*n的复杂度,用set保存,这样,查询的时候就是logn了,这样就降成了n*lgn 估计是数据太弱了,直接用n*n的竟然还快3倍多!
#include <iostream> #include <set> #include <stdio.h> using namespace std; #define MAXN 100500 __int64 queue[100000],num[MAXN],sum[MAXN]; __int64 dp[MAXN]; set<__int64 > myset; set<__int64>::iterator po; int fmin(int a,int b) { if(a<b)return a; return b; } int main() { int n,i,s,e,p; __int64 limit,ss; while(scanf("%d%I64d",&n,&limit)!=EOF) { sum[0]=0; myset.clear(); for(i=1;i<=n;i++) { scanf("%I64d",&num[i]); sum[i]=sum[i-1]+num[i]; } s=0,e=-1;p=1;ss=0; bool flag=true; for(i=1;i<=n;i++) { ss=ss+num[i]; while(ss>limit) { ss=ss-num[p++]; } if(p>i) { flag=false; break; } while(s<=e&&num[queue[e]]<=num[i]) { if(s<e) myset.erase(dp[queue[e-1]]+num[queue[e]]); e--; } queue[++e]=i; if(s<e) myset.insert(dp[queue[e-1]]+num[queue[e]]); while(s<=e&&p>queue[s]) { myset.erase(dp[queue[s]]+num[queue[s+1]]); s++; } po=myset.begin(); dp[i]=dp[p-1]+num[queue[s]]; if(s<e) { dp[i]=fmin(dp[i],*po); } } if(flag) { printf("%I64d\n",dp[n]); } else { printf("-1\n"); } } return 0; }