/***************************/
/* poj 3264
*/
/*线段树求解 RMQ 问题******/
/******Segment Tree********/
题目大意:
farmer
John 养了一群奶牛,这些奶牛呢高度不一。有一天,farmer John 心血来潮,让小牛们排队玩极限飞碟。 他将奶牛们分成若干个Group,每个Group的奶牛排成一行。由于奶牛们的高度差会影响游戏中的乐趣,因此farmerJohn 想知道,每一个Group中:第i个奶牛到第j个奶牛的范围内,最高的奶牛比最矮的奶牛高多少?
思路:
问题可以转化成求 数列下标 i~j 中最大的数与最小的数的差值。没错,这就是RMQ问题的变形。为了提高程序运行的效率,使用线段树求解RMQ问题。
ps:代码所涉及到的区间默认都是 左闭右开的.
算法步骤:
一:初始化线段树
二:分别用两个数组 dat_min[] 和 dat_max[] 来存储 区间 内的最大值和最小值。我们要求的就是 特定区间内的最大值-最小值.
三:输出结果
算法复杂度:
一:N个最后一层节点初始化,每个节点更新的复杂度为O(logN). --- O(NlogN)
二:2Q个询问,每个询问的复杂度为O(logN). --- O(2QlogN)
由于Q的取值范围比N大,则总的复杂度为 --- O(QlogN)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,N,Q;
const int INT = 0x3f3f3f3f;
const int maxn = 1 << 16;
int dat_min[2*maxn-1], dat_max[2*maxn-1];
void update(int k, int ele) {
k += n-1;
dat_min[k] = ele;
dat_max[k] = ele;
while(k > 0)
{
k = (k-1)/2;
dat_min[k] = min(dat_min[2*k+1] , dat_min[2*k+2]);
dat_max[k] = max(dat_max[2*k+1] , dat_max[2*k+2]);
}
}
void init() {
n = 1;
while(n < N)
n *= 2;
for(int i = 0 ; i < 2*n - 1 ; i ++)
{
dat_min[i] = INT;
dat_max[i] = 0;
}
}
int query_for_min(int a , int b , int l , int r , int k) {
if(b <= l || a >= r)
return INT;
else if(a <= l && b >= r)
return dat_min[k];
else
{
int lchil = query_for_min(a,b,l,(l+r)/2 ,2*k+1);
int rchil = query_for_min(a,b,(l+r)/2,r,2*k+2);
return min(lchil,rchil);
}
}
int query_for_max(int a , int b , int l , int r , int k) {
if(b <= l || a >= r)
return -1;
else if(a <= l && b >= r)
return dat_max[k];
else
{
int lchil = query_for_max(a,b,l,(l+r)/2 ,2*k+1);
int rchil = query_for_max(a,b,(l+r)/2,r,2*k+2);
return max(lchil,rchil);
}
}
int main() {
while(scanf("%d%d",&N,&Q) != EOF)
{
init();
int tmp;
for(int i = 0 ; i < N ; i ++)
{
scanf("%d",&tmp);
update(i,tmp);
}
int fr,to;
for(int i = 0 ; i < Q ; i ++)
{
scanf("%d%d",&fr,&to);
int minimum = query_for_min(fr-1,to,0,n,0);
int maximum = query_for_max(fr-1,to,0,n,0);
printf("%d\n",maximum-minimum);
}
}
return 0;
}
运行结果:
Memory: 1376K
Time : 4141MS
使用线段树解决RMQ问题:奶牛排队高度差
83

被折叠的 条评论
为什么被折叠?



