zoukankan      html  css  js  c++  java
  • [洛谷P1714]切蛋糕

    题目大意:给你n个数,要你求一段长度不超过k的、和最大的连续子序列,问你最大的和是多少。

    解题思路:单调队列+前缀和优化。

    可以发现,i到j的和与k到j的和,当j变化时,这两个和的相对大小关系是不变的。

    我们用单调队列保存与当前第i个位置距离小于k(等于则不能加到)的位置,并让这个位置加到i的和单调递减。

    这样就能保证每次从队头弹出时,之后的和仍是最大。

    求一段连续序列的和就用到前缀和优化。

    总时间复杂度$O(n)$。

    C++ Code:

    #include<cstdio>
    #include<cctype>
    #define N 500005
    int n,k,a[N],sa[N],q[N<<1],h,t;
    inline int max(int a,int b){return a<b?b:a;}
    inline int readint(){
        char c=getchar();
        bool b=false;
        for(;!isdigit(c);c=getchar())b=c=='-';
        int d=0;
        for(;isdigit(c);c=getchar())
        d=(d<<3)+(d<<1)+(c^'0');
        return b?-d:d;
    }
    int main(){
        n=readint(),k=readint();
        sa[0]=0;
        for(int i=1;i<=n;++i)sa[i]=sa[i-1]+(a[i]=readint());
        int ans=max(0,a[1]);
        if(k==1){
            for(int i=1;i<=n;++i)ans=max(ans,a[i]);
            printf("%d
    ",ans);
            return 0;
        }
        q[1]=h=t=1;
        for(int i=2;i<=n;++i){
            while(q[h]+k<=i)++h;
            while(h<=t&&a[i]>sa[i]-sa[q[t]-1])--t;
            q[++t]=i;
            ans=max(ans,sa[i]-sa[q[h]-1]);
        }
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    设计模式之观察者模式
    设计模式之装饰器模式
    redis.conf常用配置说明
    log4j日志框架的使用
    Redis入门简述
    Linux用户组权限简单解析
    MyBatis入门简述
    初学Linux要掌握的命令
    SpringIOC原理简述
    Java单元测试神器之Mockito
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/7811350.html
Copyright © 2011-2022 走看看