区间最小最大值(单调队列)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,w,a[1000001],q[10000001],id[10000001];
 4 void min()
 5 {
 6     int st=0,ed=0;
 7     for(int i=1;i<=w;i++)
 8     {
 9         while(st<ed&&q[ed]>a[i])
10         {
11             ed--;
12         }
13         ed++;
14         q[ed]=a[i];
15         id[ed]=i;
16     }
17     for(int i=w+1;i<=n;i++)
18     {
19         while(st<ed&&id[st+1]<i-w)
20         {
21             st++;
22         }
23         printf("%d ",q[st+1]);
24         while(st<ed&&q[ed]>a[i])
25         {
26             ed--;
27         }
28         ed++;
29         q[ed]=a[i];
30         id[ed]=i;
31     }
32     while(st<ed&&id[st+1]<n+1-w)
33     {
34         st++;
35     }
36     printf("%d\n",q[st+1]);
37 }
38 void max()
39 {
40     int st=0,ed=0;
41     for(int i=1;i<=w;i++)
42     {
43         while(st<ed&&q[ed]<a[i])
44         {
45             ed--;
46         }
47         ed++;
48         q[ed]=a[i];
49         id[ed]=i;
50     }
51     for(int i=w+1;i<=n;i++)
52     {
53         while(st<ed&&id[st+1]<i-w)
54         {
55             st++;
56         }
57         printf("%d ",q[st+1]);
58         while(st<ed&&q[ed]<a[i])
59         {
60             ed--;
61         }
62         ed++;
63         q[ed]=a[i];
64         id[ed]=i;
65     }
66     while(st<ed&&id[st+1]<n+1-w)
67     {
68         st++;
69     }
70     printf("%d\n",q[st+1]);
71 }
72 int main()
73 {
74     scanf("%d %d",&n,&w);
75     for(int i=1;i<=n;i++)
76     {
77         scanf("%d",&a[i]);
78     }
79     min();
80     max();
81     return 0;
82 }

题目:输入n个整数 给定w长的区间,求每个区间的最小最大值。

第一行输入n、w,

第二行开始输入n个整数;

输出时,第一行输出每个区间的最小值,用空格隔开;第二行输出每个区间的最大值,用空格隔开;

要求 1<n<10^6  1<w<=n

样例输入

8 3

1 3 -1 -3 5 3 6 7

样例输出

-1 -3 -3 -3 3 3

3 3 5 5 6 7

看到这个n的要求就知道 O(n^2)是肯定过不了了 必须在O(n)解决问题 于是就用了这个单调队列

 

大致思路如下

在队列中 我们要维护一个单调递增/递减的队列

以单调递减为例 给出样例

3 1 8 2 4 7

首先 3入队 此时队首元素为3;

接着 1入队;

1<3;

此时队首元素为3,队尾元素为1;

接着 8入队;

8>1;

为了维护递减 我们将1删除;

此时队首元素为3,队尾元素为8;

8>3;

为了维护递减 我们将3删除;

此时队首元素为8;

接着 2入队;

2<8;

此时队首元素为8,队尾元素为2;

接着4入队;

4>2;

为了维护递减 我们将2删除;

此时队首元素为8,队尾元素为4;

接着 7入队;

7>4;

为了维护递减 我们将4删除;

此时队首元素为8,队尾元素为7;

7<8;

此时 该单调队列已维护完成;

队列为 8 7;

此时 最大值就是8;

这种方法可以大大降低时间复杂度 简化排序并增强稳定性 直接得出结果 省去了其他元素排序的部分;

posted @ 2022-01-26 15:31  November&&Rain  阅读(155)  评论(0)    收藏  举报