题目链接
题目
题目描述
有一个 1 × n 1 \times n 1×n的矩阵,有 n n n个整数。现在给你一个可以盖住连续 k k k个数的木板。一开始木板盖住了矩阵的第 1 ∼ k 1 \sim k 1∼k个数,每次将木板向右移动一个单位,直到右端与第 n n n个数重合。每次移动前输出被覆盖住的数字中最大的数是多少。
输入格式
第一行两个整数
n
,
k
n,k
n,k,表示共有
n
n
n个数,木板可以盖住
k
k
k个数。
第二行
n
n
n个整数,表示矩阵中的元素。
输出格式
共
n
−
k
+
1
n−k+1
n−k+1行,每行一个整数。
第
i
i
i行表示第
i
∼
i
+
k
−
1
i \sim i + k - 1
i∼i+k−1 个数中最大值是多少。
输入输出样例
输入
5 3
1 5 3 4 2
输出
5
5
4
说明/提示
对于
20
%
20\%
20%的数据,
1
≤
k
≤
n
≤
1
0
3
1 \leq k \leq n \leq 10^3
1≤k≤n≤103。
对于
50
%
50\%
50%的数据,
1
≤
k
≤
n
≤
1
0
4
1 \leq k \leq n \leq 10^4
1≤k≤n≤104。
对于
100
%
100\%
100%的数据,
1
≤
k
≤
n
≤
2
×
1
0
6
1 \leq k \leq n \leq 2 \times 10^6
1≤k≤n≤2×106 ,矩阵中的元素大小不超过
1
0
4
10^4
104并且均为正整数。
题意
在
n
n
n个元素中选中连续
k
k
k个元素的区间,求其最大值
要求输出从
1
∼
n
−
k
+
1
1\sim n-k+1
1∼n−k+1为开头的连续
k
k
k个元素的区间的最大值,按顺序输出
思路
对每个元素使用结构体储存,每个结构体内有一个元素下标和一个元素值
以便在做双端队列时判断队头是否超出范围
- 每次插入新元素前要判断队头元素的下标是否超过了 k k k的区间范围
- 如果队尾的元素比当前要插入的元素还要小,那么肯定要弹出,要保持队列的单调递减
- 然后插入当前元素
- 判断 i i i是否处于 k ∼ n k\sim n k∼n的区间内,输出队头(即最大值)
双端队列队头为区间最大值,之后逐渐递减,与单调栈类似
#include<bits/stdc++.h>
using namespace std;
#define int long long
struct Node{
int num,number;
}a[2000010];
deque<Node> q;
int n,k;
signed main(){
scanf("%lld%lld",&n,&k);
for(int i=1;i<=n;i++)scanf("%lld",&a[i].num),a[i].number=i;
for(int i=1;i<=n;i++){
while(!q.empty()&&q.front().number+k<=i)q.pop_front();//1
while(!q.empty()&&q.back().num<a[i].num)q.pop_back();//2
q.push_back(a[i]);//3
if(i>=k)printf("%lld\n",q.front().num);//4
}
return 0;
}