码迷,mamicode.com
首页 > 其他好文 > 详细

洛谷1714

时间:2017-10-15 19:25:53      阅读:157      评论:0      收藏:0      [点我收藏+]

标签:clu   exp   com   return   插入   code   重复   main   head   

解释一下单调队列的原理(一维前缀和请自行百度)

对于这道题来讲,枚举每一个点的前缀和,然后寻找前m个点的前缀和最小值即可。

然后我们发现其实不用O(n)的扫描的,因为假设我们正在处理第i个点,除了第i-1个点没有被比较过以外

前i-1到i-m个点都被比较过了就可以利用这个原理减少重复计算。

然后单调队列,就是让一个队列,有这样的性质,队头最大(或最小),队列里的元素是不严格递减的(或不严格递增)。

在插入时就需要维护这个性质,插入时检查队尾是否比它大,大就pop掉。

这样的话每次检查队头是否有效(无效就pop),然后插入第i-1个·前缀和即可

上代码~

#include<stdio.h>
//by SHADOWICEMCMLXXXIV
using namespace std;
struct data
{
    int num;int v;
}q[500010];//手写队列
int sum[500010];
int n;int m;
int head=1;int tail=0;//初始化队列为空
void pop()//手写pop
{
    if(head<tail)head++;
    return;
}
void push(data x)//push
{
    tail++;
    q[tail]=x;
    return;
}
void pot()//pop队尾
{
    if(tail>=head)
    {
        tail--;
    }
    return;
}
int res;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&sum[i]);
        sum[i]=sum[i]+sum[i-1];//前缀和
    }
    for(int i=1;i<=n;i++)
    {
        if(q[head].num<i-m)pop();//如果队头过期就pop掉
        while(1)
        {
            if(sum[i-1]>=q[tail].v||head>tail)//如果是空队列或者是队尾比拆入的小就push
            {
                data p;p.num=i-1;p.v=sum[i-1];
                push(p);break;
            }
            else
            {
                pot();//pop队尾
            }
        }
        if(res<sum[i]-q[head].v)res=sum[i]-q[head].v;//处理最大值
    }
    printf("%d",res);
    return 0;//拜拜程序
}

洛谷1714

标签:clu   exp   com   return   插入   code   重复   main   head   

原文地址:http://www.cnblogs.com/SHADOWICENCXIX/p/7672717.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!