【单调队列】【120715测试】【朱全明NOIP模拟题】Window
样例
window.in
8 3
1 3 -1 -3 5 3 6 7
window.out
-1 -3 -3 -3 3 3
3 3 5 5 6 7
前面已经说了朴素能得30分,加上优化后能得100分
这里说说单调队列http://www.cnblogs.com/oijzh/articles/2647166.html
利用单调队列的单调性,每次入队,算最小的时候,只要当前最小的没出队,那么其他比它大的就根本不可能作为最小的输出,所以每次入队判断即可
算最大的同理
如果大家对单调队列理解不是很清楚,可以看看资料,或者看看代码,是这理解一下
单调队列 Pascal Code
program window; var n,k:longint; a:array[0..1000000+10] of longint; l,r:longint; q:array[0..1000000+10] of longint; procedure init; begin assign(input,'window.in'); assign(output,'window.out'); reset(input); rewrite(output); end; procedure outit; begin close(input); close(output); halt; end; procedure readdata; var i:longint; begin read(n,k); for i:=1 to n do read(a[i]); end; procedure main; var i:longint; begin fillchar(q,sizeof(q),0);l:=0;r:=0; for i:=1 to n do begin if q[l+1]<i-k+1 then inc(l); while (l<r)and(a[q[r]]>=a[i]) do dec(r); inc(r); q[r]:=i; if i>=k then write(a[q[l+1]],' '); end; writeln; fillchar(q,sizeof(q),0);l:=0;r:=0; for i:=1 to n do begin if q[l+1]<i-k+1 then inc(l); while (l<r)and(a[q[r]]<=a[i]) do dec(r); inc(r); q[r]:=i; if i>=k then write(a[q[l+1]],' '); end; end; begin init; readdata; main; outit; end.
附上快排优化的思路和代码
先把数据快排一次,注意要处理处一个标号数组一起快排!!!
然后n个数,每个区间k个数,那么就会有n-k+1个区间,分别用1..n-k+1表示
求最小的时候,把队列从最小开始扫描一次,比如最小是-3 标号是2 ,那么就从2开始把往前的k个区间都填成-3,(注意:要先判断该区间是否填过,填过的不能再填,因为后面的不可能比前面的更优!!!判断可以用hash数组实现),在用一个计数器count,每填一个就+1,直到count=n-k+1的时候表示全部区间填完了,就马上退出当前这个计算模块。然后计算最大的同。
Pascal Code
program window; var n,k:longint; a,nn,min,max:array[0..1000000+10] of longint; h:array[0..1000000+10] of boolean; num,maxnum:longint; procedure init; begin assign(input,'window.in'); assign(output,'window.out'); reset(input); rewrite(output); end; procedure outit; begin close(input); close(output); halt; end; procedure readdata; var i:longint; begin read(n,k); for i:=1 to n do read(a[i]); for i:=1 to n do nn[i]:=i; end; procedure qs(l,r:longint); var i,j,x,t:longint; begin i:=l;j:=r;x:=a[i+(j-i)div 2]; repeat while a[i]>x do inc(i); while a[j]<x do dec(j); if i<=j then begin t:=a[i];a[i]:=a[j];a[j]:=t; t:=nn[i];nn[i]:=nn[j];nn[j]:=t; inc(i);dec(j); end; until i>j; if i<r then qs(i,r); if l<j then qs(l,j); end; procedure workmax; var i,j,t:longint; begin fillchar(h,sizeof(h),0); maxnum:=n-k+1; num:=0; for i:=1 to n do begin t:=nn[i]; for j:=1 to k do begin if (t<1) then continue; if (not h[t])and(t<=maxnum) then begin h[t]:=true; max[t]:=a[i]; inc(num); if num=maxnum then exit; end; dec(t); end; end; end; procedure workmin; var i,j,t:longint; begin fillchar(h,sizeof(h),0); maxnum:=n-k+1; num:=0; for i:=n downto 1 do begin t:=nn[i]; for j:=1 to k do begin if t<1 then continue; if (not h[t])and(t<=maxnum) then begin h[t]:=true; min[t]:=a[i]; inc(num); if num=maxnum then exit; end; dec(t); end; end; end; procedure main; var i,j,t:longint; begin qs(1,n); //for i:=1 to n do write(a[i],' '); //找最大 workmax; //找最小 workmin; for i:=1 to n-k+1 do write(min[i],' ');writeln; for i:=1 to n-k+1 do write(max[i],' ');writeln; end; begin init; readdata; main; outit; end.
..... 转载请注明出处 ..... http://oijzh.cnblogs.com ..... by jiangzh