Time Limit: 12000MS | Memory Limit: 65536K | |
Total Submissions: 67218 | Accepted: 19088 | |
Case Time Limit: 5000MS |
Description
The array is [1 3 -1 -3 5 3 6 7], and k is 3.
Window position | Minimum value | Maximum value |
---|---|---|
[1 3 -1] -3 5 3 6 7 | -1 | 3 |
1 [3 -1 -3] 5 3 6 7 | -3 | 3 |
1 3 [-1 -3 5] 3 6 7 | -3 | 5 |
1 3 -1 [-3 5 3] 6 7 | -3 | 5 |
1 3 -1 -3 [5 3 6] 7 | 3 | 6 |
1 3 -1 -3 5 [3 6 7] | 3 | 7 |
Your task is to determine the maximum and minimum values in the sliding window at each position.
Input
Output
Sample Input
8 3 1 3 -1 -3 5 3 6 7
Sample Output
-1 -3 -3 -3 3 3 3 3 5 5 6 7
Source
这个问题用RMQ或者倍增法能在o(nlogn)内解决。 但是用双端队列(单调队列)能在o(n)内解决。 求最小值:建立一个单调递增队列,元素从左到右依次入队,入队之前必须从队列发问开始删除那些比当前入队元素大或者相等的元素,直到遇到一个比当前入队元素小的元素,或者队列为空为止。若此时队列的大小超过窗口值,则从队头删除元素,直到队列大小小入窗口值为止。然后把当前元素插入队尾。
每滑动一次,取队列的队首元素作为这一区间范围的最小值。并把超过区间范围的最小值删除。若有更小的值入队,则把队列里其它比它大的删了,因为这个最小值在它们后面,又比它们小,所以它们没有存在的意义了。
#include<stdio.h> #include<string.h> #include<stdio.h> #include<string.h> #include<stdlib.h> #include<queue> #include<stack> #include<math.h> #include<vector> #include<map> #include<set> #include<cmath> #include<string> #include<algorithm> #include<iostream> #include<string.h> #include<algorithm> #include<vector> #include<stdio.h> #include<cstdio> #include<time.h> #include<stack> #include<queue> #include<deque> #include<map> #define inf 0x3f3f3f3f #define ll long long using namespace std; int mi[1000005]; int ma[1000005]; int a[1000005]; deque<int>q; int main() { int n,k; scanf("%d %d",&n,&k); for(int i=1;i<=n;i++) scanf("%d",&a[i]); while(!q.empty ()) q.pop_back(); for(int i=1;i<=n;i++) { while(!q.empty ()&&a[q.back ()]>=a[i]) q.pop_back(); if(q.empty ()) mi[i]=i; else mi[i]=q.front (); q.push_back (i); if(q.front ()==i-k+1) q.pop_front (); } while(!q.empty ()) q.pop_back(); for(int i=1;i<=n;i++) { while(!q.empty ()&&a[q.back ()]<=a[i]) q.pop_back(); if(q.empty ()) ma[i]=i; else ma[i]=q.front (); q.push_back (i); if(q.front ()==i-k+1) q.pop_front (); } for(int i=k;i<=n;i++) { printf("%d",a[mi[i]]); if(i!=n) printf(" "); } printf("\n"); for(int i=k;i<=n;i++) { printf("%d",a[ma[i]]); if(i!=n) printf(" "); } return 0; }
Time Limit: 12000MS | Memory Limit: 65536K | |
Total Submissions: 67218 | Accepted: 19088 | |
Case Time Limit: 5000MS |
Description
The array is [1 3 -1 -3 5 3 6 7], and k is 3.
Window position | Minimum value | Maximum value |
---|---|---|
[1 3 -1] -3 5 3 6 7 | -1 | 3 |
1 [3 -1 -3] 5 3 6 7 | -3 | 3 |
1 3 [-1 -3 5] 3 6 7 | -3 | 5 |
1 3 -1 [-3 5 3] 6 7 | -3 | 5 |
1 3 -1 -3 [5 3 6] 7 | 3 | 6 |
1 3 -1 -3 5 [3 6 7] | 3 | 7 |
Your task is to determine the maximum and minimum values in the sliding window at each position.
Input
Output
Sample Input
8 3 1 3 -1 -3 5 3 6 7
Sample Output
-1 -3 -3 -3 3 3 3 3 5 5 6 7
Source
这个问题用RMQ或者倍增法能在o(nlogn)内解决。 但是用双端队列(单调队列)能在o(n)内解决。 求最小值:建立一个单调递增队列,元素从左到右依次入队,入队之前必须从队列发问开始删除那些比当前入队元素大或者相等的元素,直到遇到一个比当前入队元素小的元素,或者队列为空为止。若此时队列的大小超过窗口值,则从队头删除元素,直到队列大小小入窗口值为止。然后把当前元素插入队尾。
每滑动一次,取队列的队首元素作为这一区间范围的最小值。并把超过区间范围的最小值删除。若有更小的值入队,则把队列里其它比它大的删了,因为这个最小值在它们后面,又比它们小,所以它们没有存在的意义了。
#include<stdio.h> #include<string.h> #include<stdio.h> #include<string.h> #include<stdlib.h> #include<queue> #include<stack> #include<math.h> #include<vector> #include<map> #include<set> #include<cmath> #include<string> #include<algorithm> #include<iostream> #include<string.h> #include<algorithm> #include<vector> #include<stdio.h> #include<cstdio> #include<time.h> #include<stack> #include<queue> #include<deque> #include<map> #define inf 0x3f3f3f3f #define ll long long using namespace std; int mi[1000005]; int ma[1000005]; int a[1000005]; deque<int>q; int main() { int n,k; scanf("%d %d",&n,&k); for(int i=1;i<=n;i++) scanf("%d",&a[i]); while(!q.empty ()) q.pop_back(); for(int i=1;i<=n;i++) { while(!q.empty ()&&a[q.back ()]>=a[i]) q.pop_back(); if(q.empty ()) mi[i]=i; else mi[i]=q.front (); q.push_back (i); if(q.front ()==i-k+1) q.pop_front (); } while(!q.empty ()) q.pop_back(); for(int i=1;i<=n;i++) { while(!q.empty ()&&a[q.back ()]<=a[i]) q.pop_back(); if(q.empty ()) ma[i]=i; else ma[i]=q.front (); q.push_back (i); if(q.front ()==i-k+1) q.pop_front (); } for(int i=k;i<=n;i++) { printf("%d",a[mi[i]]); if(i!=n) printf(" "); } printf("\n"); for(int i=k;i<=n;i++) { printf("%d",a[ma[i]]); if(i!=n) printf(" "); } return 0; }