zoukankan      html  css  js  c++  java
  • POJ 3017 Cut the Sequence (单调队列优化dp)

    首先我们可以推出朴素的dp转移方程 dp[i]=min(dp[j])+max(a[j+1]...a[i])

    但是这个转移方程显然是超时的,所以我们需要对转移方程进行优化

    做这种题目的时候,我们需要对方程进行观察,我们发现,我们需要保存两种值,一个是前面已经算过的dp方程,这个很简单

    另一个是一段满足题目条件的a[i],就是最大值的关系,继而我们可以发现,如果我们对方程进行优化,我们删除的内容是要不可能取到的

    换句话来说,也就是我们需要删除 s[i]-s[头部]>m的所有值,这是从头部删除数

    还有队列中比a[i]小的数,因为在这个数之前的所有dp状态都取不到,我们取最大值是最优的

    之后我们还需枚举从这个最大值到队末的状态,因为dp值虽然变大,但是a[i]是减小的

    代码中有注释。

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<vector>
    #include<string>
    #include<cstring>
    #include<map>
    using namespace std;
    typedef long long ll;
    const int N=1e5+10;
    int q[N]; 
    ll a[N];
    ll s[N];
    ll f[N];
    int main(){
        int i;
        int n;
        ll m;
        cin>>n>>m;
        for(i=1;i<=n;i++){
            scanf("%d",&a[i]);
            s[i]=s[i-1]+a[i];
        }
        int tt=-1;
        int hh=0;
        int sign=0;
        int flag=0;
        for(i=1;i<=n;i++){
            while(i>sign&&s[i]-s[sign]>m)//将不满足条件的值都删掉,找到一个满足条件的位置 
            sign++;
            if(sign==i){
                flag=1;
                break;
            }
            while(hh<=tt&&a[i]>=a[q[tt]])//删除队列末小于等于他的值 
            tt--;
            q[++tt]=i;
            while(hh<=tt&&s[i]-s[q[hh]-1]>m) //删除队头不满足条件的值 
            hh++;
            f[i]=f[sign]+a[q[hh]];
            for(int j=hh;j<tt;j++){ //枚举最大值之后的所有情况 
                f[i]=min(f[i],f[q[j]]+a[q[j+1]]);
            }        
        }
        if(flag==1)
        cout<<-1<<endl;
        else
        cout<<f[n]<<endl;    
        
    }
    View Code
  • 相关阅读:
    jenkins本地运行方法
    项目开发规则
    finally与catch的执行
    idea中实现热部署
    vue的错误的ERR!代码ELIFECYCLE
    spring注解的使用
    mysql中with as相关用法8.0之后支持
    stream流遇到的问题
    git解决冲突,在乌龟工具中一定要点击提交
    jquery知识 内部 外部插入元素
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12262653.html
Copyright © 2011-2022 走看看