3302 范围最值问题 RMQ 线段树

效率至上

Time Limit: 5000ms   Memory limit: 65536K  有疑问?点这里^_^

题目描述

题意很简单,给出一个数目为n的非有序序列,然后有m次查询.对于每次查询输入两个正整数l,r请输出区间[l,r]的最大值与最小值的差值

输入

 第一行:输入两个正整数 n,m    (1<=n<=50000,  1<=m<=200000  )

第二行:输入n个整数  大小范围为[1,100000];

接下来的m,每次两个正整数l,r (1<=l<=r<=n);

输出

 输出区间 [l,r] 最大值与最小值的差值 .

示例输入

6 31734251 54 62 2

示例输出

630

提示

RMQ

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<vector>

using namespace std;

int d1[60000][20];
int d2[60000][20];
int T,n,m;
int a[60000];
int RMQ_init()
{
	for(int i=0;i<n;i++)
		d2[i][0]=d1[i][0]=a[i];
	for(int j=1;(1<<j)<=n;j++)
	{
		for(int i=0;i+(1<<j)-1<n;i++)
		{
			d1[i][j]=max(d1[i][j-1],d1[i+(1<<(j-1))][j-1]);
			d2[i][j]=min(d2[i][j-1],d2[i+(1<<(j-1))][j-1]);
		}
	}
}
int RMQ2(int L,int R)
{
	int k=0;
	while((1<<(k+1))<=R-L+1)
		k++;
	return min(d2[L][k],d2[R-(1<<k)+1][k]);
}
int RMQ1(int L,int R)
{
	int k=0;
	while((1<<(k+1))<=R-L+1)
		k++;
	return max(d1[L][k],d1[R-(1<<k)+1][k]);
}
int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		for(int i=0;i<n;i++)
			scanf("%d",&a[i]);
		RMQ_init();
		for(int i=0;i<m;i++)
		{
			int r,b;
			scanf("%d%d",&r,&b);//
			printf("%d\n",RMQ1(r-1,b-1)-RMQ2(r-1,b-1));
		}
	}
}

#include<iostream>  //线段树
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#define lson l,mid,site<<1
#define rson mid+1,r,site<<1|1

using namespace std;

struct node
{
	int left,right;
}score[2000000];
int n,m;
int PushUp(int site)
{
	score[site].left=max(score[site<<1].left,score[site<<1|1].left);
	score[site].right=min(score[site<<1].right,score[site<<1|1].right);
}
int Build(int l,int r,int site)
{
	if(l==r)
	{
		scanf("%d",&score[site].left);
		score[site].right=score[site].left;
		return 0;
	}
	int mid=(l+r)>>1;
	Build(lson);
	Build(rson);
	PushUp(site);
}
//int UpData(int a,int b,int l,int r,int site)
//{
//	if(l==r)
//	{
//		score[site].left=b;
//		score[site].right=b;
//		return 1;
//	}
//	int mid=(l+r)>>1;
//	if(a<=mid)
//		UpData(a,b,lson);
//	else
//		UpData(a,b,rson);
//	PushUp(site);
//}
int Query1(int L,int R,int l,int r,int site)
{
	if(L<=l&&R>=r)
		return score[site].left;
	int mid=(l+r)>>1;
	if(R<=mid)
		return Query1(L,R,lson);
	else if(L>mid)
		return Query1(L,R,rson);
	else
		return max(Query1(L,mid,lson),Query1(mid+1,R,rson));
}
int Query2(int L,int R,int l,int r,int site)
{
	if(L<=l&&R>=r)
		return score[site].right;
	int mid=(l+r)>>1;
	if(R<=mid)
		return Query2(L,R,lson);
	else if(L>mid)
		return Query2(L,R,rson);
	else
		return min(Query2(L,mid,lson),Query2(mid+1,R,rson));
}
int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		Build(1,n,1);
		while(m--)
		{
			int a,b;
			scanf("%d%d",&a,&b);
			printf("%d\n",Query1(a,b,1,n,1)-Query2(a,b,1,n,1));
		}
	}
}


你可能感兴趣的:(3302 范围最值问题 RMQ 线段树)