POJ 2823
POJ 2823 Sliding Windows
题目大意:给出一个长度为n的数组(1<=n<=10^6),然后
For I := 1 to n-k+1 do 问区间a[I,i+k-1]内的最大最小值。
解法:复杂度最高去到n^2,显然不能朴素询问,用单调队列去维护即可,用min举例,如果新+入的数比队尾大,则保留(以后可能会用到),若小,则不断dec(mint),直到比队尾大为止(为什么?其实就是一个贪心,新数进入窗口,说明数在窗口期间都是有效的,前面几个比它大的已经不用保存了,是一种贪心的思想),我是用了一个time数组来处理一个数是否在窗口内,比较麻烦,不知道是否有更好的方法了。
{提出一个nlogn的算法,快排一下从第一个开始更新区间}
View Code
1 //poj p2823
2 //orz fjy, this story from the way to gdoi2011
3 const
4 maxn=1000000;
5 var
6 a, qmin, qmax: array[1..maxn]of longint;
7 mint, maxt, minh, maxh, n, k, tot: longint;
8 pr, time: array[1..2, 1..maxn]of longint;
9 procedure min(x, timing: longint);
10 begin
11 if x>qmin[mint] then inc(mint)
12 else
13 begin
14 inc(mint);
15 while (mint>minh)and(x<=qmin[mint-1]) do dec(mint);
16 end;
17 qmin[mint] := x;
18 time[1, mint] := timing;
19 end;
20
21 procedure max(x, timing: longint);
22 begin
23 if x<qmax[maxt] then inc(maxt)
24 else
25 begin
26 inc(maxt);
27 while (maxt>maxh)and(x>=qmax[maxt-1]) do dec(maxt);
28 end;
29 qmax[maxt] := x;
30 time[2, maxt] := timing;
31 end;
32
33 procedure init;
34 var
35 i: longint;
36 begin
37 fillchar(time ,sizeof(time), 0);
38 minh := 1;
39 mint := 1;
40 maxh := 1;
41 maxt := 1;
42
43 readln(n, k);
44 for i := 1 to n do read(a[i]); readln;
45 qmin[1] := a[1];
46 qmax[1] := a[1];
47 for i := 2 to k do
48 begin
49 min(a[i], i);
50 max(a[i], i);
51 end;
52 tot := 1;
53 pr[1, 1] := qmin[minh];
54 pr[2, 1] := qmax[maxh];
55 end;
56
57 procedure main;
58 var
59 i, j: longint;
60 begin
61 for i := k+1 to n do
62 begin
63 inc(tot);
64 min(a[i], i);
65 max(a[i], i);
66 while (i-time[1, minh]>=k) do inc(minh);
67 while (i-time[2, maxh]>=k) do inc(maxh);
68 pr[1, tot] := qmin[minh];
69 pr[2, tot] := qmax[maxh];
70 end;
71 end;
72
73 procedure print;
74 var
75 i, j: longint;
76 begin
77 for j := 1 to 2 do
78 begin
79 for i := 1 to tot do
80 begin
81 if i<>1 then write(' ');
82 write(pr[j, i]);
83 end;
84 writeln;
85 end;
86 end;
87
88 begin
89 {assign(input,'test.in'); reset(input);
90 assign(output,'test.out'); rewrite(output); }
91 init;
92 main;
93 print;
94 //close(input);
95 end.