单调栈(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 }

 

(我太菜了,,,数组模拟调了半个小时。。)

posted @ 2019-01-01 19:48  Let_Life_Stop  阅读(187)  评论(0编辑  收藏  举报