zoukankan      html  css  js  c++  java
  • hdu3415:最大k子段和,单调队列

    题目大意:
    给定长度为n的数组,求出最大的区间和,其中区间长度在[1,k]之间

    分析:

    学动态规划的时候我们会遇到一个经典问题

    最大子段和,这个题跟最大子段和很类似 不同的是区间的长度有限制,无法用原算法解决

    转换思路

    区间[i,j]的和就是ans=sum(j)-sum(i-1) ( j - i <=k)

    那么对于每个j 我们肯定希望sum(i-1)最小,所以我们只需要对sum(i-1)维护一个单调队列,然后依次增加 j

    同时将单调队列中不满足( j - i <k)的元素出队即可

    代码:

    #include <iostream>
    #include <stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<string>
    #include<ctype.h>
    using namespace std;
    #define maxn 10000010
    typedef struct Node
    {
        int val;
        int num;
    }node;
    typedef struct dqueue
    {
        node q[maxn];
        int l,r;
        void ini()
        {
            l=0;
            r=0;
        }
        node front()
        {
            return q[l];
        }
        node pop()
        {
            l++;
            return q[l-1];
        }
        void push(node x)
        {
            if(r==l)
            {
                q[r++]=x;
                return;
            }
            if(x.val<q[l].val)
            {
                r=l;
                q[r++]=x;
                return;
            }
            while(r>=1&&(x.val<q[r-1].val))
            {
                r--;
            }
            q[r++]=x;
        }
    }Dqueue;
    int a[200020];
    int sum[200020];
    Dqueue q;
    int main()
    {
        int n,k,T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&k);
            sum[0]=0;
            for(int i=1;i<=n;i++)
            {
                scanf("%d",a+i);
            }
            memcpy(a+n+1,a+1,n*sizeof(int));
            for(int i=1;i<=2*n;i++)
            {
                sum[i]=sum[i-1]+a[i];
            }
            node x;
            node tmp;
            int t=0;
            q.ini();
            int ans=-10000;
            int l,r;
            for(int i=1;i<=2*n;i++)
            {
                x.val=sum[i-1];
                x.num=i-1;
                q.push(x);
                while(1)
                {
                    tmp=q.front();
                    if(i-tmp.num>k)
                    {
                        q.pop();
                    }
                    else
                    {
                        break;
                    }
                }
                if(sum[i]-tmp.val>ans)
                {
                    ans=sum[i]-tmp.val;
                    l=tmp.num+1;
                    r=i;
                    continue;
                }
            }
            if(r>n)
            {
                r-=n;
            }
            printf("%d %d %d
    ",ans,l,r);
        }
        return 0;
    }
  • 相关阅读:
    MySQL技术内幕 InnoDB存储引擎 之 InnoDB体系架构
    ORACLE同义词使用
    五大好用的开源MySQL管理工具推荐
    MySQL Online DDL工具
    10046事件及其用法介绍
    MySQL表碎片清理
    MyRocks安装部署
    TiDB单机安装测试
    TiDB官方文档
    GoldenGate—AUTORESTART配置
  • 原文地址:https://www.cnblogs.com/oneshot/p/4048938.html
Copyright © 2011-2022 走看看