单调队列(oj1771)

来源:互联网 发布:光纤端口一收一发 编辑:程序博客网 时间:2024/06/07 06:35

先看道题
这里写图片描述

很显然,这题可以用堆去做。解法具体可以去看我以前写的博客

然而这不是重点。。。

重点是写一个堆太eggache了
有没有其它办法?

那就是单调队列


设一个单调递增队列d

何为递增?
后面的数一定比前面的小

先不管怎么实现,如果一直维护着一个单调队列,那么它的头元素一定是最小/大的。
因为它是队列里最小/大的数啊。。


那么问题来了
怎么维护

主要是插入元素
因为要维护单调的性质,所以如果当前的元素和尾元素产生冲突(大/小)时,
就把尾元素丢掉
当然如果整个队列都被扔了,那么新元素就是头元素

关于查找

有时候题目会加上一些奇怪的性质(比如烽火传递),有时候头元素不能用
那么就直接丢掉,直到能用为止

代码

var        a:array[1..100000] of longint;        f:array[1..100000] of longint;        d:array[1..100000,1..2] of longint;        n,m,i,h,t,ans:longint;procedure put(s,s2:longint);var        i:longint;begin        while (h<=t) and (d[t,1]>=s) do        dec(t);        inc(t);        d[t,1]:=s;        d[t,2]:=s2;end;function min(x,y:longint):longint;begin        if x<y then min:=x        else        min:=y;end;procedure swap(var x,y:longint);var        z:longint;begin        z:=x;        x:=y;        y:=z;end;procedure qsort(l,r:longint);var        i,j,mid:longint;begin        i:=l;        j:=r;        mid:=d[(l+r) div 2,1];        while i<=j do        begin                while (d[i,1]<mid) do inc(i);                while (d[j,1]>mid) do dec(j);                if i<=j then                begin                        swap(d[i,1],d[j,1]);                        swap(d[i,2],d[j,2]);                        inc(i);                        dec(j);                end;        end;        if l<j then qsort(l,j);        if i<r then qsort(i,r);end;begin        assign(Input,'beacon.in'); reset(Input);        assign(Output,'beacon.out'); rewrite(Output);        readln(n,m);        for i:=1 to n do        readln(a[i]);        for i:=1 to m do        begin                f[i]:=a[i];                d[i,1]:=a[i];                d[i,2]:=i;        end;        h:=1;        t:=m;        qsort(1,t);        for i:=m+1 to n do        begin                while (h<=t) and (d[h,2]+m<i) do                inc(h);                f[i]:=d[h,1]+a[i];                put(f[i],i);        end;        ans:=maxlongint;        for i:=n-m+1 to n do        ans:=min(ans,f[i]);        writeln(ans);        close(Input); close(Output);end.