#rMQybttg040202. 1542:【例 2】最敏捷的机器人
1542:【例 2】最敏捷的机器人
好的,我将这道题整理为清晰的题面格式,并补充样例解释、数据范围与时空限制:
题目描述
Wind 设计了很多机器人。但是它们都认为自己是最强的,于是,一场比赛开始了……
机器人们都想知道谁是最敏捷的,于是它们进行了如下一个比赛。首先,它们面前会有一排共 个数,它们比赛看谁能最先把每连续 个数中最大和最小值写下来,当然,这些机器人运算速度都很快,它们比赛的是谁写得快。
但是 Wind 也想知道答案,你能帮助他吗?
输入格式
第一行为两个整数 ,意义如题目描述。
第二行包含 个整数,为数字序列,所有数字均在 Pascal 的 longint 范围内,即所有数均为整数,且在 范围内。
输出格式
共 行,第 行为第 至第 这 个数中的最大值和最小值,两个数之间用一个空格隔开。
样例
样例输入
5 3
1 2 3 4 5
样例输出
3 1
4 2
5 3
样例说明
,序列 。
连续 个数的窗口:
- 窗口 :,最大值 ,最小值 ;
- 窗口 :,最大值 ,最小值 ;
- 窗口 :,最大值 ,最小值 。
输出共 行。
数据范围
对于全部数据:
时空限制
- 时间:
- 内存:(512 MB)
提示
此题为 滑动窗口最值 问题,可以用 单调队列 在线性时间内解决。
方法:
- 维护两个双端队列:一个单调递减(用于最大值),一个单调递增(用于最小值);
- 遍历 从 到 :
- 若队首下标超出窗口范围(),则弹出队首;
- 在最大值队列中,从队尾弹出所有值 的下标,保证队列递减;
- 在最小值队列中,从队尾弹出所有值 的下标,保证队列递增;
- 将 加入两个队列;
- 当 时,输出最大值队列队首对应的值 和 最小值队列队首对应的值。
复杂度:,每个元素入队出队一次。
注意:
- 最大 , 完全可行;
- 输入输出量较大,建议使用
scanf/printf或关闭同步的cin/cout; - 注意数据范围,数列元素在 int 范围内,但中间计算不会溢出。
代码框架:
deque<int> q_max, q_min;
for (int i = 1; i <= n; i++) {
// 维护最大值队列(递减)
while (!q_max.empty() && a[q_max.back()] <= a[i]) q_max.pop_back();
q_max.push_back(i);
if (q_max.front() < i - k + 1) q_max.pop_front();
// 维护最小值队列(递增)
while (!q_min.empty() && a[q_min.back()] >= a[i]) q_min.pop_back();
q_min.push_back(i);
if (q_min.front() < i - k + 1) q_min.pop_front();
if (i >= k) {
printf("%d %d\n", a[q_max.front()], a[q_min.front()]);
}
}