zoukankan      html  css  js  c++  java
  • cf 1077 区间dp 双向队列保存区间最大值

    http://codeforces.com/contest/1077/problem/F2

    题意:给定n,k,x; 表示长为n的序列中,每长为k的一段必须有一个数被选择

      在选择x次之后,得到的最大值

    思路:简单的n,k,x<=200的时候 可以nkx的dp

      但是对于nkx<=4000的  这样就超市

    但是我们可以上面的思路修改一下

    d[i][j]表示 第i次选择,选择最后面的位置为j 这时候的最大值

      d[0][0]=0;
    
        for(int i=1;i<=x;++i){
            for(int j=1;j<=n;++j)
                for(int q=1;q<=k;++q)
                    if(j-q<0)continue;
                    else if(d[i-1][j-q]!=-1)
                    d[i][j] = max(d[i-1][j-q]+a[j],d[i][j]);
        }

    上面是nkx的复杂度

    针对于内层循环,我们可以改进一下:

    内层选择的 :    在符合<=k的条件下,取出这个区间的最大值

    那么如果用双向队列(i前面的数已经入队)

    1.那么把  j-Q.front()>k  的进行pop_back(),这样剩下的都是符合条件的了

    2.那如何保证一个最大值呢?

    假设我们这次走到了 d[i][j] 那么应该讲 d[i-1][j-1]push进去

    如果在此之前  将尾部所有比d[i-1[j-1]的 元素pop_back()  

    在最初 deque是个递减的 那么这样叠加下去,仍然是递减的

    所以deque里的头部永远是这一段的最大值

    #include<bits/stdc++.h>
    using namespace std;
    
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define pii pair<int,int>
    #define time __time
    
    const int N  =2e5+4;
    ll a[N],b[N];
    
    ll d[5222][5222];
    
    int main(){
    
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n,x,k;
        cin>>n>>k>>x;
    
        for(int i=1;i<=n;++i)cin>>a[i];
        if( n/k>x  ){
            printf("-1
    ");
            return 0;
        }
        memset(d,-1,sizeof(d));
    
        d[0][0]=0;
    
        deque<int>Q;
        for(int i=1;i<=x;++i){
            for(int j=1;j<=n;++j){
                while(!Q.empty() &&j-Q.front()>k )
                    Q.pop_front();
                while(!Q.empty() &&d[i-1][Q.back()] <= d[i-1][j-1] )
                    Q.pop_back();
                Q.push_back(j-1);
                if(d[i-1][Q.front()]!=-1)
                    d[i][j] = d[i-1][Q.front()]+a[j];
            }
            while(!Q.empty())Q.pop_back();
        }
        ll ans = -1;
        for(int q=n;q>n-k;--q){
            ans = max(ans,d[x][q]);
        }
        cout<<ans<<endl;
    
        return 0;
    }
  • 相关阅读:
    Javascript的作用域、作用域链以及闭包
    C#当中的泛型和java中的对比
    MongoDB的主从复制和副本集
    MongoDB启动配置等
    JavaScript学习系列1 基础-变量
    Umbraco项目发布错误 --More than one type want to be a model for content type authorize
    项目中gulp使用发生的错误及解决
    JavaScript学习系列2一JavaScript中的变量作用域
    ASP.NET MVC中的ActionFilter介绍学习
    Razor中的 内容标记块语法
  • 原文地址:https://www.cnblogs.com/wjhstudy/p/9985958.html
Copyright © 2011-2022 走看看