poj 3017 dp+单调队列优化
2012-09-18 14:51
351 查看
/* 题意:给你一个长度为n的数列,要求把这个数列划分为任意块,每块的元素和小于m,使得所有块的最大值的和最小 分析:这题很快就能想到一个DP方程 f[ i ]=min{ f[ j ] +max{ a[ k ] }}( b[ i ]<j<i,j<k<=i) b[ i ]到 i的和大于m 这个方程的复杂度是O(n^2),明显要超时的(怎么discuss都说数据弱呢= =) 然后是优化了,首先当然是要优化一个最大值的队列,使得这个队列的队首元素的到当前位置的和不超过m, 这样一个可行解就是,f[ i ]=f[b[ i ]-1]+a[ q[ l ]](即队首元素的值), 这并不是最优解,所以还要找到队列中的最优解,一个可能的最优解只能是这样的 f[ q[ j ] ]+ a[ q[j +1 ]],也就是 a[ j ] 要大于后面的数, 很显然,如果a[ j ]小于后面的数,那么我们就可以将 a[ j ] 划分到后面去,而取得更优解 这里涉及的这个找最优解问题, 因为一个m 定义成int WA了无数次。。。。伤不起!!! */ #include<iostream> #include<algorithm> #include<set> #include<cstdio> #include<cstring> using namespace std; const int maxn=110002; int q[maxn],a[maxn],pre,n; __int64 sum,Max[maxn],m; int main() { scanf("%d%I64d",&n,&m); int i,j,l=0,r=-1,flag=0; pre=1,sum=0; Max =-1; multiset<int>s; s.clear(); for(i=1; i<=n; i++) { scanf("%d",&a[i]); sum+=a[i]; while(sum>m) sum-=a[pre++]; if(a[i]>m) flag=1; if(flag) continue; while(l<=r&&a[i]>=a[q[r]]) { if(l<r)s.erase(Max[q[r-1]]+a[q[r]]); r--; } q[++r]=i; if(l<r) s.insert(Max[q[r-1]]+a[q[r]]); while(q[l]<pre) { if(l<r)s.erase(Max[q[l]]+a[q[l+1]]); l++; } Max[i]=Max[pre-1]+a[q[l]]; __int64 ans=*s.begin(); if(l<r&&Max[i]>ans) Max[i]=ans; } if(flag) printf("-1\n"); else { printf("%I64d\n",Max ); } return 0; }
相关文章推荐
- POJ 3017 单调队列优化DP
- POJ - 3017 Cut the Sequence : 单调队列优化dp
- poj 3017 Cut the Sequence dp+单调队列优化
- POJ 3017 Cut the Sequence (单调队列优化DP)
- poj 3017 Cut the Sequence(dp单调队列优化)
- poj 3017 单调队列优化DP
- POJ-3017 Cut the Sequence(DP单调队列优化 + 平衡树)
- Poj 3017 Cut the Sequence (DP,单调队列优化,数据结构优化)
- POJ 3017 Cut the Sequence 【DP+单调队列优化+平衡树】
- poj 3017 Cut the Sequence(DP+单调队列+set)
- POJ Cut the Sequence 单调队列优化DP入门题
- POJ 3017 单调队列+最值优化 的动态规划
- POJ 3017 Cut the Sequence(DP + 单调队列优化 + 平衡树)
- UVaLive 4327 | POJ 3926 - Parade (单调队列优化DP)
- POJ - 3017 Cut the Sequence(单调队列+dp)
- POJ 2373 单调队列优化DP
- POJ 3017 单调队列dp
- POJ 2823 Sliding Window - dp&单调队列优化
- poj 2823 单调队列优化DP
- poj 1821 Fence(dp单调队列优化)