单调栈(G - Sliding Window POJ - 2823 )
题目链接:https://cn.vjudge.net/contest/276251#problem/G
题目大意:给你n和m,然后问你对于(m,n)这中间的每一个数,(i-m+1,i)这个区间的最小值和最大值。
具体思路:单调队列,对于个数的控制,我们通过队列来实现一个模拟的滑动窗口。然后最值的寻找,我们可以通过控制队列保持单调递增或者单调递减来实现。
STL AC代码(耗时:10985s):
1 #include<iostream> 2 #include<stack> 3 #include<cmath> 4 #include<string> 5 #include<stdio.h> 6 #include<algorithm> 7 #include<cstring> 8 #include<queue> 9 using namespace std; 10 # define inf 0x3f3f3f3f 11 # define ll long long 12 const int maxn = 1e6+100; 13 int minn[maxn],maxx[maxn],sto[maxn]; 14 inline int read1() 15 { 16 int f=1,x=0; 17 char s=getchar(); 18 while(s<'0' || s>'9') 19 { 20 if(s=='-') 21 f=-1; 22 s=getchar(); 23 } 24 while(s>='0' && s<='9') 25 { 26 x=x*10+s-'0'; 27 s=getchar(); 28 } 29 return x*f; 30 } 31 int main() 32 { 33 int n,m; 34 n=read1(); 35 m=read1(); 36 // scanf("%d %d",&n,&m); 37 deque<int>q1; 38 deque<int >q2; 39 int tot=0,tmp; 40 for(int i=1;i<=n;i++){ 41 sto[i]=read1(); 42 } 43 for(int i=1; i<=n; i++) 44 { 45 while(!q1.empty()&&q1.front()<i-m+1)//先判断左边界有没有超出范围 46 q1.pop_front(); 47 while(!q1.empty()&&sto[i]<sto[q1.back()])//保持队列单调递增 48 { 49 q1.pop_back(); 50 } 51 q1.push_back(i); 52 if(i>=m) 53 minn[++tot]=q1.front(); 54 while(!q2.empty()&&q2.front()<i-m+1) 55 q2.pop_front(); 56 while(!q2.empty()&&sto[i]>sto[q2.back()]) 57 { 58 q2.pop_back(); 59 } 60 q2.push_back(i); 61 if(i>=m) 62 maxx[tot]=q2.front(); 63 } 64 for(int i=1; i<=tot; i++) 65 { 66 if(i==1) 67 printf("%d",sto[minn[i]]); 68 else 69 printf(" %d",sto[minn[i]]); 70 } 71 printf("\n"); 72 for(int i=1; i<=tot; i++) 73 { 74 if(i==1) 75 printf("%d",sto[maxx[i]]); 76 else 77 printf(" %d",sto[maxx[i]]); 78 } 79 printf("\n"); 80 return 0; 81 }
数组模拟(耗时:7152ms)AC代码:
1 #include<iostream> 2 #include<stack> 3 #include<cmath> 4 #include<string> 5 #include<stdio.h> 6 #include<algorithm> 7 #include<cstring> 8 #include<queue> 9 using namespace std; 10 # define inf 0x3f3f3f3f 11 # define ll long long 12 const int maxn = 1e6+100; 13 int minn[maxn],maxx[maxn],sto[maxn]; 14 int moni[maxn]; 15 inline int read1() 16 { 17 int f=1,x=0; 18 char s=getchar(); 19 while(s<'0' || s>'9') 20 { 21 if(s=='-') 22 f=-1; 23 s=getchar(); 24 } 25 while(s>='0' && s<='9') 26 { 27 x=x*10+s-'0'; 28 s=getchar(); 29 } 30 return x*f; 31 } 32 int main() 33 { 34 int n,m; 35 n=read1(); 36 m=read1(); 37 int l=1,r=0; 38 int tot=0; 39 for(int i=1; i<=n; i++) 40 { 41 sto[i]=read1(); 42 } 43 for(int i=1; i<=n; i++) 44 { 45 while(l<=r&&moni[l]<i-m+1) 46 l++; 47 while(l<=r&&sto[i]<sto[moni[r]]){ 48 r--; 49 } 50 moni[++r]=i; 51 if(i>=m) 52 minn[++tot]=moni[l]; 53 } 54 l=1,r=0,tot=0; 55 for(int i=1; i<=n; i++) 56 { 57 while(l<=r&&moni[l]<i-m+1) 58 l++; 59 while(l<=r&&sto[i]>sto[moni[r]]){ 60 r--; 61 } 62 moni[++r]=i; 63 if(i>=m) 64 maxx[++tot]=moni[l]; 65 } 66 for(int i=1; i<=tot; i++) 67 { 68 if(i==1) 69 printf("%d",sto[minn[i]]); 70 else 71 printf(" %d",sto[minn[i]]); 72 } 73 printf("\n"); 74 for(int i=1; i<=tot; i++) 75 { 76 if(i==1) 77 printf("%d",sto[maxx[i]]); 78 else 79 printf(" %d",sto[maxx[i]]); 80 } 81 printf("\n"); 82 return 0; 83 }
(我太菜了,,,数组模拟调了半个小时。。)