Week5 作业 D - 滑动窗口 POJ - 2823

题目描述:

有一个长度为 n 的数列和一个大小为 k 的窗口, 窗口可以在数列上来回移动. 求在窗口从左往右滑的时候,每次窗口内数的最大值和最小值分别是多少. 例如:
数列是 [1 3 -1 -3 5 3 6 7], 其中 k 等于 3.

思路:

求最小值时,维护一个单调递增队列,基本操作:

①元素进队操作:如果当前元素大于队尾则进队,否则弹出队尾,直到队空或者队尾元素小于当前元素;

②先把前k个元素都进队;

③从第k+1个元素到第n个元素遍历:遍历第i个元素时,当前队首的元素一定是第i-k个滑动窗口中的最小值;然后把过期的元素从队首删除,把第i个元素进队;遍历完n个元素之后,最后队首的元素是最后一个滑动窗口的最小值。

同理可以用单调递减队列求最大值。

正确性:

单调递增队列中的队首元素一定是最小元素

 代码:

值得注意的是,用G++交超时,用C++交能过,原因不想追究,因为我一直在寻找问题,直到题面更新了尝试G++和C++...

STL的deque,支持队首和队尾都删除。 

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <queue>
 4 #include <deque>
 5 using namespace std;
 6 const int MAXN=1e6+5;
 7 deque<int> Q;
 8 int a[MAXN],maxi[MAXN],mini[MAXN];  //maxi[j]=k,第j个滑动窗口的最大值是k 
 9 int n,k;
10 int main()
11 {
12     cin>>n>>k;
13     for(int i=1;i<=n;i++)
14         scanf("%d",a+i); 
15     for(int i=1;i<=k;i++)
16     {
17         while( !Q.empty() && a[i]< a[ Q.back() ] )
18             Q.pop_back();
19         Q.push_back(i);
20     }
21     for(int i=k+1;i<=n;i++)
22     {
23         mini[i-k]=a[ Q.front() ];  //第i-k个滑动窗口的最小值就是队头
24         while( !Q.empty() && i-Q.front()>=k )
25             Q.pop_front();
26         while( !Q.empty() && a[i]< a[ Q.back() ] )
27             Q.pop_back();
28         Q.push_back(i);
29     }
30     mini[n+1-k]=a[ Q.front() ];
31     Q.clear();
32     
33     for(int i=1;i<=k;i++)
34     {
35         while( !Q.empty() && a[i]>a[ Q.back() ] )
36             Q.pop_back();
37         Q.push_back(i);
38     }
39     for(int i=k+1;i<=n;i++)
40     {
41         maxi[i-k]=a[ Q.front() ];  //第i-k个滑动窗口的最大值就是队头,但是i-k可能小于0,加了一个偏移MAXN 
42         while( !Q.empty() && i-Q.front()>=k )
43             Q.pop_front();
44         while( !Q.empty() && a[i]>a[Q.back()] )
45             Q.pop_back();
46         Q.push_back(i);
47     }
48     maxi[n+1-k]=a[ Q.front() ];
49         
50     int t2=n-k+1;
51     printf("%d",mini[1]);
52     for(int i=2;i<=t2;i++)
53         printf(" %d" , mini[i] );
54     printf("\n%d",maxi[1]);
55     for(int i=2;i<=t2;i++)
56         printf( " %d" , maxi[i] );
57     return 0; 
58 }

猜你喜欢

转载自www.cnblogs.com/qingoba/p/12615922.html