zoukankan      html  css  js  c++  java
  • 单调队列优化dp+决策单调性——poj3017好题

    /*
    dp[i]表示前i个数的最优解
    dp[i]=min{ dp[j]+max[j+1,i] },sum[i]-sum[j]<=M 
    使用决策单调性:显然dp[i]是单调递增的
        那么维护一个区间[j+1,i]关于a的递减单调队列q
        对于a[q[1]]可以控制的决策范围是[j+1,q[1]],又因为决策单调性,所以这一段区间的最优解就是dp[j+1]+a[q[1]]
        同理,遍历整个队列,可得后面每一段的最佳决策
    */ 
    #include<iostream>
    #include<queue>
    #include<cstdio> 
    using namespace std;
    #define ll long long 
    #define N 200005
    
    ll n,M,a[N],sum[N],dp[N];
    
    int main(){
        cin>>n>>M;
        for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
        for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i];
        for(int i=1;i<=n;i++)if(a[i]>M){
            puts("-1");return 0;
        }
        
        memset(dp,0x3f,sizeof dp);dp[0]=0;
        deque<int>q;
        deque<int>::iterator it,itt;
        int pos=1;
        for(int i=1;i<=n;i++){
            while(sum[i]-sum[pos-1]>M)pos++;
            while(q.size()){//删前面 
                int p=q.front();
                if(sum[i]-sum[p-1]>M)q.pop_front();
                else break;
            }
            while(q.size()){//删后面 
                 int p=q.back();
                 if(a[p]<=a[i])q.pop_back();
                 else break;
            }
            q.push_back(i);
            for(it=q.begin();it!=q.end();it++){
                if(it==q.begin()){
                    dp[i]=min(dp[i],a[*it]+dp[pos-1]);
                }else {
                    itt=it;itt--;
                    dp[i]=min(dp[i],a[*it]+dp[*itt]);
                }
            }
        }
        cout<<dp[n]<<'
    ';
    } 
  • 相关阅读:
    ARP投毒攻击
    sniffer简单使用
    MAC泛洪攻击
    又是一题反序列化了解一下???
    关于parse_str变量覆盖分析
    超级ping(多线程版)
    文本输入框input将输入转换为统一大小写
    通俗易懂JSONP讲解
    通俗易懂JSONP讲解
    Fastjson主要接口和类库说明
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12512137.html
Copyright © 2011-2022 走看看