HDU 3415单调队列

来源:互联网 发布:签名设计软件下载 编辑:程序博客网 时间:2024/04/29 05:09

这个题目属于常见题型,给定一组环状数列,求出其中长度不超过k的数字之和的最大值。。

用到了前缀和的技巧,比如要求i,j间所有数字之和,可以提前在输入的时候计算出从0~i的数字之和及从0~j的数字之和,那么sum[i~j]=sum[j]-sum[i];

现在的问题是求出最大的sum[i~j].那么我们可以固定sum[j]的值,当sum[i]最小时,整个式子值最大。。显然会用到单调递增队列,不断维护进队出队操作即可,

保持单调递增队列的单调性不被破坏,则队头元素始终是最小的值;

至于sum[j]不断枚举就行了,至此问题得到完美解决。

下面是我的代码,调了半天才发现一个极其SB的错误,维护进队操作时,应该用sum[q[tail]]和sum[cur]比较进行删除队尾元素的操作,我不知道为何手贱的写成了sum[q[head]]......T_T,地球人已经阻止不了我犯二的脚步了~~QAQ


 

/******************************
* author :crazy_石头
* data structure: 单调队列
* created time:2013/112/31 23:27
* Pro:HDOJ 3415
* Judge Status:Accepted
* Memory:2098K
* Time:171MS
* PS:可以优化输入输出加速,ORZ
* 这题也很基础,不过多了起始点和结束点的维护罢了;
*******************************/

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>

using namespace std;

#define rep(i,h,m) for(int i=(h);i<=(m);i++)
#define INF 0x3fffffff

const int maxn=100000+5;
int sum[maxn<<1],q[maxn<<1],a[maxn<<1];//q存储下标,元素的值可以通过访问下标间接访问到;
int res,test;
int head,tail,n,k;
int start,end;

inline void Enqueue(int cur)//维护单调递增队列入队过程;
{
    while(head<=tail&&sum[q[tail]]>sum[cur])
        tail--;//当队列不空且待插入元素小于队尾元素时,删除队尾元素,以维护队列单调递增性质;
    q[++tail]=cur;//记录下标;
}

inline void Dequeue(int cur)//不断维护该操作即可;
{
    while(head<=tail&&q[head]<cur-k)
        head++;//当队列不空且队头不在给定范围之内时删除队头元素;
    if(sum[cur]-sum[q[head]]>res)//不断更新res;
    {
        res=sum[cur]-sum[q[head]];
        start=q[head]+1;//记录起点和终点;
        end=cur;
    }
}

int main()
{
    scanf("%d",&test);
    while(test--)
    {
        memset(sum,0,sizeof(sum));
        scanf("%d%d",&n,&k);

        head=1,tail=0;
        res=-INF;
        rep(i,1,n)
        {
            scanf("%d",&a[i]);
            sum[i]=sum[i-1]+a[i];//维护前缀和;
        }
        rep(i,n+1,n+k)
            sum[i]=sum[i-1]+a[i-n];//处理循环数列的方法:在其后面复制一串数字;

        Enqueue(0);
        rep(i,1,n+k)
        {
            Dequeue(i);
            Enqueue(i);
        }
        printf("%d %d %d\n",res,start>n?start-n:start,end>n?end-n:end);
    }
    return 0;
}

* This source code was highlighted byYcdoiT. ( style: Fog )

原创粉丝点击