码迷,mamicode.com
首页 > 其他好文 > 详细

poj 3017 Cut the Sequence

时间:2015-09-05 22:13:04      阅读:277      评论:0      收藏:0      [点我收藏+]

标签:

poj 3017 Cut the Sequence

单调队列

题意是:把一个 长度 为 n 的 数列 分成任意份,使每一份的和不超过m,求每一份的最大值的和,使和最小

动态规划方程 是 f [i] = f[j] + max{ f[j+1] , f[j+2] , f[i] };

朴素的算法是 O(n^2);

用 单调队列 表示一个递减 的 队列 ,则 不需要 求 每块区域的最大值

哎哎哎……不知道怎么说

技术分享
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <deque>
#include <iterator>
using namespace std;
typedef long long ll;
const int MAXN=10e5+10;
const int INF=0x7fffffff;
ll arr[MAXN];
ll f[MAXN];
int main(){
//    freopen("input.txt","r",stdin);
    int n;
    ll m;
    while(~scanf("%d%I64d",&n,&m)){
        f[0]=0;
        deque<int>dq;
        while(!dq.empty()){
            dq.pop_back();
        }
        int k=0;
        bool flag=0;
        ll sum=0;
        for(int i=1;i<=n;i++){
            scanf("%I64d",&arr[i]);
            if(flag){
                continue;
            }
            if(arr[i]>m){
                flag=1;
                continue;
            }
            sum += arr[i];
            while(sum > m){
                sum -= arr[++k];
            }
            while(!dq.empty() && arr[dq.back()]<=arr[i]){
                dq.pop_back();
            }
            dq.push_back(i);
            while(!dq.empty() && dq.front() <= k){
                dq.pop_front();
            }
            int kk=k;
            f[i] = INF;
            for(deque<int>::iterator it=dq.begin();it<dq.end();it++){
                f[i]=min(f[kk]+arr[*it],f[i]);
                kk=*it;
            }
        }
        printf("%I64d\n",flag?-1:f[n]);
    }
    return 0;
}
View Code

广告印刷……
题意:一排 宽度为 1 ,长度不同 的 高楼,在上面印 矩形 广告,求矩形的 最大 印刷 面积

木桶的短板原理,最短的会拉低矩形的高度。

对于某点 i ,以点为最低点, 左边能 延续的 最大长度 ,和右边 所能延续的 最大距离 ,则面积 就 求出

左延续需要借助 一个 递增 的单调队列 则 前面的 高度,一定可以代表可以 到达 i 的 矩形,如果 以 i 为 最低点作为矩形的话

则 需要从 单调队列队尾的 下一个 点开始 则宽度 为 i - dq.back() - 1

 右延续同上,从右边到左的 递增 的 单调序列 求 宽度 dq.back() - i - 1;

技术分享
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <deque>
using namespace std;
//广告印刷,需要求队列里面的最小值,维持递增的单调队列
const int MAXN = 4000000+10;
int h[MAXN];
int L[MAXN];
int R[MAXN];
int main(){
    freopen("input.txt","r",stdin);
    int n;
    deque<int>dq;
    while(~scanf("%d",&n)){
        int ans = 0;
        while(!dq.empty()){
            dq.pop_back();
        }
        dq.push_back(0);
        h[0]=h[n+1]= -1;
        for(int i=1;i<=n;i++){
            scanf("%d",&h[i]);
            while(!dq.empty() && h[dq.back()] >= h[i]){
                dq.pop_back();
            }
            L[i]=i-dq.back()-1;
            dq.push_back(i);
        }
        while(!dq.empty()){
            dq.pop_back();
        }
        dq.push_back(n+1);
        for(int i=n;i>0;i--){
            while(!dq.empty() && h[dq.back()] >= h[i]){
                dq.pop_back();
            }
            R[i]=dq.back()-i-1;
            ans=max(ans,h[i]*(R[i]+L[i]+1));
            dq.push_back(i);
        }
        printf("%d\n",ans);
    }
    return 0;
}
View Code

 

poj 3017 Cut the Sequence

标签:

原文地址:http://www.cnblogs.com/hanbinggan/p/4782307.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!