0
点赞
收藏
分享

微信扫一扫

最敏捷的机器人

晚熟的猫 2022-01-08 阅读 71

RMQ 什么是RMQ呢? RMQ是用来求一段区间内的最大最小值的一种算法

寒假训练第一周
Wind 设计了很多机器人。但是它们都认为自己是最强的,于是,一场比赛开始了……

机器人们都想知道谁是最敏捷的,于是它们进行了如下一个比赛。首先,他们面前会有一排共 nn 个数,它们比赛看谁能最先把每连续 kk 个数中最大和最小值写下来,当然,这些机器人运算速度都很快,它们比赛的是谁写得快。

但是 Wind 也想知道答案,你能帮助他吗?

输入格式
第一行为 n,kn,k,意义如题目描述。

第二行共 nn 个数,为数字序列,所有数字均在 Pascal 的 longint 范围内,即所有数均为整数,且在 [-2{31},2{31}-1][−2
31
,2
31
−1] 范围内。

输出格式
共 n-k+1n−k+1 行,第 ii 行为第 ii 至第 i+k-1i+k−1 这 kk 个数中的最大和最小值。

用数组f[i][j] 表示从数组a[i]开始到i+2^j这段区间中的最大(小)的值,这样可以节省很多时间(树上倍增)比如数组 1 3 2 5 6 7 8 10 4 -1 6我们要求从2到10需要跳几次(只能往前跳,而且每次只能跳2的次方步) 我们可以先求出log10/log2 也就是log2(10) 求出9最大是2的几次方 那我们求出是3 从2^3开始跳 2+8=10正好到达10 这个例子不太恰当 换个例子 从2 跳到11 我们算出来依然最多跳2^3步 2+2^2 到了10 接下来是2^2 10+4=14>11所以我们不能跳2^2 接下来是2^1 10+2>11 也不可以 2^0 10+1=11 就可以了 这就是我们在跳的时候的基本思想

#include<stdio.h>
#include<algorithm>
using namespace std;
int a[1000010],log[2000000],f[200000][25],z[200000][25];
int main()
{
	int i,j,k,m,n;
	scanf("%d%d",&n,&k);
	for(i=1;i<=n;i++)
	scanf("%d",&a[i]);
	log[0]=-1;
	for(i=1;i<=n;i++)
	f[i][0]=a[i],log[i]=log[i>>1]+1,z[i][0]=a[i];//预处理出log   
	for(j=1;j<=20;j++)//从2的20次方开始尝试 
	{
		for(i=1;i+(1<<j)-1<=n;i++)//i+1<<j要小于n 保证在区间内  
		f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]),//把i到j分为两个区间 最大值等于 从i跳 2^j-1步   从i+2^J-1  再跳j-
		步 
		z[i][j]=min(z[i][j-1],z[i+(1<<j-1)][j-1]);//同理 
	}
	for(i=1;i<=n-k+1;i++)
	{
		int x=i;
		int y=i+k-1;
		int s=log[y-x+1];//区间长度 
		printf("%d %d\n",max(f[x][s],f[y-(1<<s)+1][s]),min(z[x][s],z[y-(1<<s)+1][s]));	
	}
	return 0;
}
 
举报

相关推荐

0 条评论