poj 3017 单调队列

只能说是代码美如画。(当然我是指内在逻辑不是我的代码风格,队长看到要理解哈,啊哈哈哈哈哈哈哈哈)

正常思路咯,f[i]=f[j]+max(a[j+1],a[j+2]....a[i]),枚举j,显然硬来会超时,所以需要有一个单调队列来时时把最大值尽快弄出来并且需要一些剪枝;

剪枝条件有两个,一个是和不能超过m,一个是显然f[i]是个非严格递增序列,根据这两个条件剪枝;

则建立单调队列,每当插入新的i时将前面先把和小于等于m的条件做好,然后对于j<i,如果a[j]<a[i]就可以把j丢弃,那么显然新加入的元素会成为单调队列中最小的,则单调队列为递减序列。

然后就看代码吧

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <set>
 4 #include <iostream>
 5 #include <map>
 6 #include <math.h>
 7 #include <algorithm>
 8 #include <vector>
 9 using namespace std;
10
11 typedef long long ll;
12
13 const int N=100005;
14 const long long INF=1000000000ll;
15 int n;
16 ll m;
17 ll a[N],f[N];
18 ll solve(){
19 int i,j,k=0,fg=0,l=0,r=0;
20 int q[N];
21 ll sum=0;
22 for(i=1;i<=n;i++){
23     sum+=a[i];
24     while(sum>m) sum-=a[++k];
25     if(k>=i){
26         fg=1;
27         break;
28     }
29    while(l<=r&&a[q[r]]<=a[i]) r--;//等于号是细节
30    q[++r]=i;
31    while(l<=r&&q[l]<=k) l++;
32    ll tmp;
33    int kk=k;
34       f[i]=INF;
35         //cout<<l<<" "<<r<<" "<<kk<<endl;
36         for ( j=l; j<=r; j++) //队列优化后的dp过程,加入过程保证了单调队列中元素是递减的
37         {
38             tmp=f[kk]+a[q[j]];
39           //cout<<tmp<<" "<<f[i]<<" "<<i<<" "<<kk<<endl;
40             if (tmp<f[i]) f[i]=tmp;
41             kk=q[j]; //kk表示当前最值存在的区间范围是[kk+1,i]
42         }
43 //f[i]=tmp;
44 //cout<<f[i]<<" "<<i<<endl;
45 }
46 if(fg)
47     return -1;
48 else
49     return f[n];
50 }
51 int main()
52 {
53    freopen("in.txt","r",stdin);
54    cin>>n>>m;
55    int i;
56    for(i=1;i<=n;i++)
57     scanf("%lld",&a[i]);
58   cout<<solve()<<endl;
59     return 0;
60 }
时间: 2024-12-16 21:35:19

poj 3017 单调队列的相关文章

POJ 3017 单调队列dp

Cut the Sequence Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 8764   Accepted: 2576 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 subseque

Sliding Window POJ - 2823 单调队列模板题

Sliding Window POJ - 2823 单调队列模板题 题意 给出一个数列 并且给出一个数m 问每个连续的m中的最小\最大值是多少,并输出 思路 使用单调队列来写,拿最小值来举例 要求区间最小值 就是维护一个单调递增的序列 对于样例 8 3 1 3 -1 -3 5 3 6 7 我们先模拟一遍 1.队列为空 1 进队 队列:1 2.3>队尾元素 3 进队 队列: 1 3 3.-1小于队尾元素,一直从尾部出队知道找到比-1小的元素或者队列为空 队列:-1 当队列中元素大于m的时候从队头删

POJ 2838 单调队列

Sliding Window Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 55309   Accepted: 15911 Case Time Limit: 5000MS Description An array of size n ≤ 106 is given to you. There is a sliding window of size k which is moving from the very left

poj 2823 单调队列

//单调队列求滑动窗口的最大值和最小值 //题意是给一个n个数,在每k个数区间内 //求最大值和最小值 //单调队列:队列中的元素是单调的. //求最小值的时候:进队的时候将队尾部大于当前要进的元素全部出队 //这样,队列的头部就是最小值 //反之,求最大值也是一样 #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> using namespace std

poj 2823 单调队列裸题

两个队列分别维持最大和最小 #include<stdio.h> #include<string.h> #include<iostream> using namespace std; struct node { int mi,ma; }num[1000010]; int sax[1000010],sin[1000010]; int ida[1000010],idi[1000010]; int main() { int n,m,i,j,k,a; while(~scanf(&

poj 2823 单调队列 deque写法

Sliding Window Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 46435   Accepted: 13417 Case Time Limit: 5000MS Description An array of size n ≤ 106 is given to you. There is a sliding window of size k which is moving from the very left

poj 3017 Cut the Sequence(单调队列优化 )

题目链接:http://poj.org/problem?id=3017 题意:给你一个长度为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都说数据弱呢= =) 然后是优化了,首先当然是要优化一个最大

POJ 3017 Cut the Sequence (单调队列优化DP)

POJ 3017 Cut the Sequence (单调队列优化DP) ACM 题目地址: POJ 3017 Cut the Sequence 题意: 将一个由N个数组成的序列划分成若干段,要求每段数字的和不超过M,求[每段的最大值]的和 的最小的划分方法,输出这个最小的和. 分析: 方程是:dp[i] = min(dp[j]+maxsum[j+1][i]) 但复杂度n*n太高,需要优化. 可以用单调队列+BST优化,其实只需要维护每一段的最大值. 看了这篇题解的:http://blog.cs

POJ 3670 Eating Together 二分单调队列解法O(nlgn)和O(n)算法

本题就是一题LIS(最长递增子序列)的问题.本题要求求最长递增子序列和最长递减子序列. dp的解法是O(n*n),这个应该大家都知道,不过本题应该超时了. 因为有O(nlgn)的解法. 但是由于本题的数据特殊性,故此本题可以利用这个特殊性加速到O(n)的解法,其中的底层思想是counting sort分段的思想.就是如果你不会counting sort的话,就很难想出这种优化的算法了. O(nlgn)的单调队列解法,利用二分加速是有代表性的,无数据特殊的时候也可以使用,故此这里先给出这个算法代码