zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Word快捷键大全
    IT人物TOP100英雄人物榜
    关于简历的理解
    opengl头文件:错误: 无法打开包括文件:“gl/glut.h”: No such file or directory
    关于两次算法竞赛的心得
    MFC中关于将控件与成员变量绑定,实现用子类重载控件
    怎么入门
    正则表达式
    每天更新,督促自己学习
    测试人员的出路
  • 原文地址:https://www.cnblogs.com/beiyuoi/p/6216129.html
Copyright © 2011-2022 走看看