题目描述
Wind 设计了很多机器人。但是它们都认为自己是最强的,于是,一场比赛开始了……
机器人们都想知道谁是最敏捷的,于是它们进行了如下一个比赛。首先,他们面前会有一排共 n 个数,它们比赛看谁能最先把每连续 k 个数中最大和最小值写下来,当然,这些机器人运算速度都很快,它们比赛的是谁写得快。
但是 Wind 也想知道答案,你能帮助他吗?
输入格式
第一行为 n,k,意义如题目描述。
第二行共 n 个数,为数字序列,所有数字均在 Pascal
的 longint
范围内,即所有数均为整数,且在 [−2^31,2^31−1] 范围内。
输出格式
共 n−k+1 行,第 i 行为第 i 至第 i+k−1这 k个数中的最大和最小值。
样例
样例输入
5 3
1 2 3 4 5
样例输出
3 1
4 2
5 3
数据范围与提示
对于全部数据,1≤k≤n≤10^5
在普通rmq的基础上再加一个存最小值的数组就行了
(其实跟模板题没什么区别,但是为了水博客,我还是决定再发一遍)
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N = 1e6 + 3;
int logg[N],f[N][20],s[N][20],a[N];
int n,k;
int main()
{
scanf("%d%d",&n,&k);
for(int i = 1;i <= n;i++)
{
scanf("%d",&a[i]);
}
logg[0] = -1;
for(int i = 1;i <= n;i++)
{
f[i][0] = a[i];
s[i][0] = a[i];
logg[i] = logg[i >> 1] + 1;
}
for(int i = 1;i <= 21;i++)
{
for(int j = 1;j + (1 << i) - 1 <= n;j++)
{
f[j][i] = max(f[j][i - 1],f[j + (1 << i - 1)][i - 1]);
s[j][i] = min(s[j][i - 1],s[j + (1 << i - 1)][i - 1]);
}
}
int q = logg[k];
for(int i = 1;i <= n - k + 1;i++)
{
printf("%d %d\n",max(f[i][q],f[i + k - 1 - (1 << q) + 1][q]),min(s[i][q],s[i + k - 1 - (1 << q) + 1][q]));
}
return 0;
}