标签:acm
点击打开链接 题目链接
Time Limit: 12000MS | Memory Limit: 65536K | |
Total Submissions: 40565 | Accepted: 11982 | |
Case Time Limit: 5000MS |
Description
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
用一个长度为k的窗在整数数列上移动,求窗里面所包含的数的最小值最大值。
单调队列定义:
a)从队头到队尾,元素在我们所关注的指标下是递减的(严格递减,而不是非递增),比如查询如果每次问的是窗口内的最小值,那么队列中元素从左至右就应该递增,如果每次问的是窗口内的最大值,则应该递减,依此类推。这是为了保证每次查询只需要取队头元素。
b)从队头到队尾,元素对应的时刻(此题中是该元素在数列a中的下标)是递增的,但不要求连续,这是为了保证最左面的元素总是最先过期,且每当有新元素来临的时候一定是插入队尾。
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int que[1111111],num[1111111],maxn[1111111],minn[1111111],index[1111111]; int n,k; void getmin() { int fr=1,ed=0,i; for(i=0;i<k-1;i++) { while(fr<=ed&&que[ed]>=num[i]) ed--; que[++ed]=num[i]; index[ed]=i; } for(;i<n;i++) { while(fr<=ed&&que[ed]>=num[i]) ed--; que[++ed]=num[i]; index[ed]=i; while(index[fr]<i-k+1) { fr++; } minn[i-k+1]=que[fr]; } } void getmax() { int fr=1,ed=0,i; for(i=0;i<k-1;i++) { while(fr<=ed&&que[ed]<=num[i]) ed--; que[++ed]=num[i]; index[ed]=i; } for(;i<n;i++) { while(fr<=ed&&que[ed]<=num[i]) ed--; que[++ed]=num[i]; index[ed]=i; while(index[fr]<i-k+1) { fr++; } maxn[i-k+1]=que[fr]; } } int main() { //freopen("acm.txt","r",stdin); scanf("%d %d",&n,&k); for(int i=0;i<n;i++) { scanf("%d",&num[i]); } getmin(); getmax(); for(int i=0;i<n-k+1;i++) { if(i<n-k) printf("%d ",minn[i]); else printf("%d\n",minn[i]); } for(int i=0;i<n-k+1;i++) { if(i<n-k) printf("%d ",maxn[i]); else printf("%d\n",maxn[i]); } return 0; }
标签:acm
原文地址:http://blog.csdn.net/qq_16843991/article/details/41551829