zoukankan      html  css  js  c++  java
  • 《算法竞赛进阶指南》0x59单调队列优化DP AcWing 299裁剪序列

    题目链接:https://www.acwing.com/video/864/

    给定一个长度为n的序列,问将这个序列分成连续的若干段,每段不超过M的情况下,每段的最大值之和最小是多少?

    如果数据范围比较小的话就可以不进行任何优化,用dp[i]表示将[1,i]分成若干段满足条件的情况下每段最大值最小的情况,那么dp[j]就容易从dp[i]进行转移,但是转移中存在一个max函数,不是单调的。

    所以需要对决策集合进行考虑。

    复杂度较高的情况:

    第一次筛选:找到最小的j使得[j+1,i]之间的和是不超过M的。

    第二次筛选:在左边决策变量j对应的值不超过右边序列的最大值的情况下尽量向左延伸。因为这样右侧的最大值不会发生变化,但是左侧的最大值和不会变大,所以总的最大值之和不会变大。容易知道这种情况下A[j]就是[j,i]序列的最大值。所以我们需要维护的就是满足这样一个性质的序列,如果有一个决策点j1和j2,满足j1<j2而且a[j1]<=a[j2],那么显然可以再向左延伸而不会使结果变的更差。

    由于计算的是f[j]+max{A[k]}(j+1<=k<=i),不满足单调性,因此上述每一个决策j都需要进行计算,从中找到最小的就是f[i]。

    通过单调队列就能维护这样一个决策变量j的可能取值,而f[i]最初的取值是最左端j对应的f[j]+q[l],其中q[l]是单调队列中的首元,也就是[j+1,i]中最大值对应的下标。

    容易知道,对每个q[k],下一个数q[k+1]就是q[k]之后最大的数对应的下标。

    证明:假设q[k]右侧的A的最大值对应的索引为s,如果A[s]<=A[q[k+1]],条件满足,如果s>q[k+1],根据单调队列的性质,应该去除q[k+1]点,并且加入s,但是队列当前已经满足性质,故s点一定是q[k+1]。

    证毕。

    该算法保证每个决策在队列中只被扫描一遍,但最坏的情况下可以达到O(n^2)。通过堆优化能保持O(nlogn)时间复杂度。堆用来在对数时间内查找最小值,要满足插入和删除操作,其中删除操作需要谨慎处理。

    代码1:POJ能过3017

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<set>
    using namespace std;
    const int N = 100010;
    typedef long long ll;
    int n;
    ll m;
    ll a[N];
    ll q[N];
    ll f[N];
    int main(){
        scanf("%d%lld",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            if(a[i]>m){
                puts("-1");
                return 0;
            }
        }
        int l=0,r=0;
        ll sum = 0;
        for(int i=1,j=0;i<=n;i++){
            sum+=a[i];
            while(sum>m)sum-=a[++j];//初步筛选所有可能的j 
            while(l<=r && q[l]<=j)l++;
            while(l<=r && a[q[r]]<=a[i])r--;
            q[++r]=i;//二次筛选所有可能的j 
            
            f[i]=f[j]+a[q[l]];//第二种情况或者第一种情况中的边界 
            for(int k=l;k<r;k++)
                f[i]=min(f[i],f[q[k]]+a[q[k+1]]);
        }
        
        cout<<f[n]<<endl;
        
        return 0;
    }

     

  • 相关阅读:
    nyoj256-C小加之级数求和
    nyoj254-编号统计
    nyoj286-动物统计
    最长回文子串——manacher
    动态规划:Codeforces Round #427 (Div. 2) C Star sky
    水题:51Nod1432-独木舟
    水题:HDU1716-排列2
    水题:CF16C-Monitor
    数学基础:HUD1124-Factorial(N!末尾0的个数)
    并查集:POJ1182-食物链(并查集比较高端的应用)
  • 原文地址:https://www.cnblogs.com/randy-lo/p/13425053.html
Copyright © 2011-2022 走看看