• BZOJ 2086: [Poi2010]Blocks


    Description

    每次可以将大于 (k) 的一个数 (-1), 在左边或右边的数 (+1) ,问最大能得到多长的序列每个数都大于等于 (k) .

    Sol

    单调栈.

    这道题好神啊qwq...思路++

    首先如果一段序列满足 (sum_{i=l}^ri geqslant k(r-l+1)) 那么这个序列就是合法的,把所有的数都 (-k) 那么只需要满足非负即可.

    然后从前往后找一个单调递减的前缀和序列,如果有小于等于前面的某个位置的前缀和,那么选这个不如选前面大于等于他的那个位置.

    然后倒着做,右端点递减的时候,左端点要满足递减才能对答案产生贡献,就用一个栈来维护就行.

    Code

    /**************************************************************
        Problem: 2086
        User: BeiYu
        Language: C++
        Result: Accepted
        Time:4768 ms
        Memory:20820 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
    using namespace std;
     
    typedef long long LL;
    const int N = 1e6+50;
     
    LL n,m,ans;
    LL a[N],s[N];
    int stk[N],top;
     
    inline LL in(LL x=0,char ch=getchar()) { while(ch>'9' || ch<'0') ch=getchar();
        while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();return x; }
    int main() {
        n=in(),m=in();
        for(int i=1;i<=n;i++) a[i]=in();
        for(;m--;) {
            LL x=in();top=0,ans=0;
            for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i]-x;
            for(int i=1;i<=n;i++) if(s[i]<s[stk[top]]) stk[++top]=i;
            for(int i=n;i>=0;i--) {
                while(top && s[i]-s[stk[top-1]]>=0) top--;
                ans=max(ans,(LL)i-stk[top]);
            }printf("%lld%c",ans,"
     "[m>0]);
        }
        return 0;
    }
    
  • 相关阅读:
    Golang关键字—— var
    Ubuntu下搭建Golang开发环境
    CentOS安装MongoDB
    使用2-3法则设计分布式数据访问层
    8 种提升 ASP.NET Web API 性能的方法
    MongoDB 聚合之 MapReduce
    常用开源项目及工具汇总——持续更新
    了解一下jsp
    前苹果副总裁:如果你做的事情毫不费力,就是在浪费时间
    思考
  • 原文地址:https://www.cnblogs.com/beiyuoi/p/6216129.html
Copyright © 2020-2023  润新知