poj之旅——3264

//2886又没理解,诶诶,语言障碍

题目描述:给出n个人的升高,有T个询问【i,j】,求从i到j最高-最矮的差。


题解:典型的rmq问题,hankcs用的平方分割(术语称:块状数组),不喜欢,自己打的Square—Table算法,和线段树练练手。


参考程序:

ST:

#include<cstdio>
#include<algorithm>
#define maxn 51000
using namespace std;
int a[maxn];
int n,q;
struct RMQ{
	int n;
	void init(int n){
		this->n=n;
	}
	int Max[maxn][30];
	int Min[maxn][30];
	void prepare(){
		for (int i=0;i<n;i++)
			Max[i][0]=a[i],Min[i][0]=a[i];
		for (int j=1;(1<<j)<=n;j++)
			for (int i=0;i+(1<<j)<=n;i++){
				Max[i][j]=max(Max[i][j-1],Max[i+(1<<(j-1))][j-1]);
				Min[i][j]=min(Min[i][j-1],Min[i+(1<<(j-1))][j-1]);
			}
	}
	int query(int l,int r){
		int k=0;
		while ((1<<(k+1))<=r-l+1)k++;
		int tmax=max(Max[l][k],Max[r-(1<<k)+1][k]);
		int tmin=min(Min[l][k],Min[r-(1<<k)+1][k]);
		return tmax-tmin;
	}
}form;
int main(){
	scanf("%d%d",&n,&q);
	form.init(n);
	for (int i=0;i<n;i++)
		scanf("%d",&a[i]);
	form.prepare();
	while (q--){
		int from,to;
		scanf("%d%d",&from,&to);
		printf("%d\n",form.query(from-1,to-1));
	}
	return 0;
}

线段树:

#include<cstdio>
#include<algorithm>
#define maxn 51000
#define INF 0x7f7f7f7f
using namespace std;
int n,q;
struct Segment{
	int left[3*maxn+10],right[3*maxn+10];
	int Max[3*maxn+10],Min[3*maxn+10];
	int tmax,tmin;
	void build(int no,int l,int r){
		int mid=(l+r)>>1;
		left[no]=l;right[no]=r;
		Max[no]=-INF;Min[no]=INF;
		if (l+1<r){
			build(2*no,l,mid);
			build(2*no+1,mid,r);
		}
	}
	void replace(int no,int l,int data){
		if (left[no]+1==right[no]){
			Max[no]=max(Max[no],data);
			Min[no]=min(Min[no],data);
		}else{
			int mid=(left[no]+right[no])>>1;
			if (l<mid)replace(2*no,l,data);
				else replace(2*no+1,l,data);
			Max[no]=max(Max[2*no],Max[2*no+1]);
			Min[no]=min(Min[2*no],Min[2*no+1]);	
		}
	}
	int query_max(int no,int l,int r){
		if (l<=left[no] && right[no]<=r){
			return Max[no];
		}else{
			int mid=(left[no]+right[no])>>1;
			int tmp=-INF;
			if (l<mid)tmp=query_max(2*no,l,r);
			if (r>mid)tmp=max(tmp,query_max(2*no+1,l,r));
			return tmp;
		}
	}
	int query_min(int no,int l,int r){
		if (l<=left[no] && right[no]<=r){
			return Min[no];
		}else{
			int mid=(left[no]+right[no])>>1;
			int tmp=INF;
			if (l<mid)tmp=query_min(2*no,l,r);
			if (r>mid)tmp=min(tmp,query_min(2*no+1,l,r));
			return tmp;
		}
	}
}tree;
int main(){
	scanf("%d%d",&n,&q);
	tree.build(1,0,n);
	for (int i=0;i<n;i++){
		int a;
		scanf("%d",&a);
		tree.replace(1,i,a);
	}
	while (q--){
		int from,to;
		scanf("%d%d",&from,&to);
		printf("%d\n",tree.query_max(1,from-1,to)-tree.query_min(1,from-1,to));
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值