POJ 3017 Cut the Sequence 【DP+单调队列优化+平衡树】
2017-01-16 10:14
555 查看
题意
给定一串数列,要求把它划分成一些小段,每个小段的和不超过M,找到一种分段方法使得每一段的最大值的和最小,求这个最小值分析
易得转移方程dp[i]=min(dp[k]+max(num[k+1],⋯,num[i]))
其中∑ij=k+1num[j]<=M,朴素的做法显然是O(n2)的。观察可得dp数组是递增的,然后对于一个确定的分段最大值,以该最大值所在位置左边开始的分段的最大值至少比这个最大值要大。可知最大值必须是单调递减的。因此对于一个确定的最大值的位置,要使得dp[k]+maxj最小,k必须尽量往左取,也就是取到上一个最大值的位置,或者是使得分段和为M的位置。这样我们就可以用单调队列维护递减的最大值,但是单调队列的开头的元素并不一定是最优值,因此还要用平衡树维护整个单调队列中每个位置对应的dp+num以快速求得最优值
AC代码
//POJ 3017 Cut the Sequence //AC 2017-1-16 10:03:12 //DP, monotonic Queue, BBT #include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <cctype> #include <cstdlib> #include <cstring> #include <vector> #include <set> #include <string> #include <map> #include <queue> #include <deque> #include <list> #include <sstream> #include <stack> using namespace std; #define cls(x) memset(x,0,sizeof x) #define inf(x) memset(x,0x3f,sizeof x) #define neg(x) memset(x,-1,sizeof x) #define ninf(x) memset(x,0xc0,sizeof x) #define st0(x) memset(x,false,sizeof x) #define st1(x) memset(x,true,sizeof x) #define lowbit(x) x&(-x) #define input(x) scanf("%d",&(x)) #define inputt(x,y) scanf("%d %d",&(x),&(y)) #define bug cout<<"here"<<endl; //#pragma comment(linker, "/STACK:1024000000,1024000000")//stack expansion //#define debug const double PI=acos(-1.0); const int INF=0x3f3f3f3f;//1061109567-2147483647 const long long LINF=0x3f3f3f3f3f3f3f3f;//4557430888798830399-9223372036854775807 const int maxn=1e5+100; int N; long long M,sum; long long num[maxn],dp[maxn]; int monque[maxn],s,e,beg; multiset<long long> optset; int main() { //ios::sync_with_stdio(false); //cin.tie(0); #ifdef debug freopen("E:\\Documents\\code\\input.txt","r",stdin); freopen("E:\\Documents\\code\\output.txt","w",stdout); #endif //IO while(scanf("%d %lld",&N,&M)!=EOF) { for(int i=0;i<N;++i) scanf("%lld",num+i); s=e=beg=0; sum=0; optset.clear(); for(int i=0;i<N;++i) { if(num[i]>M) { dp[N-1]=-1; break; } sum+=num[i]; while(sum>M) sum-=num[beg++]; while(s<e&&num[monque[e-1]]<=num[i]) { if(s<e-1) optset.erase(dp[monque[e-2]]+num[monque[e-1]]); --e; } monque[e++]=i; if(s<e-1) optset.insert(dp[monque[e-2]]+num[monque[e-1]]); while(s<e&&monque[s]<beg) { if(s<e-1) optset.erase(dp[monque[s]]+num[monque[s+1]]); ++s; } dp[i]=dp[beg-1]+num[monque[s]]; if(s<e-1) dp[i]=min(dp[i],*optset.begin()); } printf("%lld\n",dp[N-1]); } return 0; }
相关文章推荐
- 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 Cut the Sequence (单调队列优化DP)
- poj 3017 Cut the Sequence(dp单调队列优化)
- POJ - 3017 Cut the Sequence : 单调队列优化dp
- poj 3017 Cut the Sequence(DP+单调队列+set)
- poj 3017 Cut the Sequence(单调队列优化 )
- POJ 3017 Cut the Sequence(dp+单调队列)
- poj 3017 Cut the Sequence(DP+单调队列)
- POJ Cut the Sequence 单调队列优化DP入门题
- POJ_3017 Cut the Sequence 单调队列+dp+BST
- POJ - 3017 Cut the Sequence(单调队列+dp)
- [poj3017] Cut the Sequence (DP + 单调队列优化 + 平衡树优化)
- POJ-3017 Cut the Sequence DP+单调队列+堆
- POJ--3017--Cut the Sequence--DP优化
- POJ 3017 Cut the Sequence(单调队列+set)
- poj3017 Cut the Sequence 单调队列优化dp 好题!
- Cut the Sequence,Sequence Partitioning,POJ3017,POJ3245,用单调队列优化的DP