您的位置:首页 > 其它

单调队列(oj1771)

2017-06-23 20:51 316 查看
先看道题



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

然而这不是重点。。。

重点是写一个堆太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);

cf7c
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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: