zoukankan      html  css  js  c++  java
  • [Usaco2009 Open]干草堆

    来自一个弱鸡的随笔单调队列 动态规划

    题目链接:http://forioi.com/contest/problem?id=56&pid=9#problem-anchor

    g[j]<=s[i]-s[j],即s[j]+g[j]<=s[i],若有 k<j且g[k]+s[k]>=g[j]+s[j]则k永远不可能再转移别人了,因为如果k满足转移条件,那么j也会满足,而j的位置还更加靠后。

    因此,我们可以维护一个 g+s值单调递增的单调队列。

    每次转移时从单调队列中找到最后一个g[j]+s[j]<=s[i]的位置j,单调队列中j以左的元素从队首出队。

    转以后从队尾弹出g[j]+s[j]>=g[i]+s[i]的元素,然后将位置i加入单调队列。

    每个元素进出队列各一次,复杂度为O(n)。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=100005;
    int n,a[maxn],s[maxn],f[maxn],g[maxn],q[maxn],l,r;
    int main()
    {
        scanf("%d",&n);
        for(int i=n;i;--i)
            scanf("%d",a+i);
        for(int i=1;i<=n;++i)
            s[i]=s[i-1]+a[i];
        for(int i=1;i<=n;++i)
        {
            while(l<r&&s[q[l+1]]+g[q[l+1]]<=s[i])
                ++l;
            f[i]=f[q[l]]+1;
            g[i]=s[i]-s[q[l]];
            while(l<r&&s[q[r]]+g[q[r]]>=s[i]+g[i])
                --r;
            q[++r]=i;
        }
        printf("%d",f[n]); 
        return 0;
    }

    有木有很清爽啊~

  • 相关阅读:
    web测试方法总结
    我认为测试应该掌握的SQL语句
    monkey(1)
    冒烟测试
    PC客户端测试总结
    常见测试点总结
    测试基本概念
    测试主要环节
    手机app常见bug积累
    MySQL面试题集锦
  • 原文地址:https://www.cnblogs.com/backcl/p/13426301.html
Copyright © 2011-2022 走看看