查找m----n个数中最值之差
使用线段树构造一颗二叉树,
typedef struct tree
{
int L;
int R;
int max;
int min;
}tree;
并且给这个树中的最值赋值
值保存在一个数组a[]中
void bulid(int t,int i,int j)
{
c[t].L=i;
c[t].R=j;
c[t].max = -N;
c[t].min = N;
if(c[t].L==c[t].R)
{
c[t].max = a[c[t].L];
c[t].min = a[c[t].L];
return ;
}
bulid(t*2,i,(int)(i+j)/2 );
bulid(t*2+1,(int)(i+j)/2+1,j);
c[t].max = ( c[t*2].max>c[t*2+1].max?c[t*2].max:c[t*2+1].max);
c[t].min = ( c[t*2].min<c[t*2+1].min?c[t*2].min:c[t*2+1].min);
}
接着就是查找这个数中某个区间的最值之差
这个分为两种情况
1. 是这棵书中节点中有这个区间的m--n
2. 是这区间跨了这个数的左右节点,就是有一半在左孩子中有一半在右孩子中。
讨论这两种情况就好了
最后得到这个区间的最值
输出最值之差
void print(int x,int y,int t)
{
if(c[t].L>=x&&c[t].R<=y)//
{
if(c[t].max>l_max) l_max = c[t].max;
if(c[t].min<l_min) l_min = c[t].min;
return ;
}
int xx =(c[t].L+c[t].R)/2;
if(y<=xx)
{
print(x,y,t*2);
}
else if(x>=xx+1)
{
print(x,y,t*2+1);
}
else
{
print(x,xx,t*2);
print(xx,y,t*2+1);
}
}
完整代码:
#include<stdio.h>
#include<string.h>
#define N 1000010
typedef struct tree
{
int L;
int R;
int max;
int min;
}tree;
tree c[N];
int a[N];
int l_max = 0,l_min = N*100 ;
void bulid(int t,int i,int j)
{
c[t].L=i;
c[t].R=j;
c[t].max = -N;
c[t].min = N;
if(c[t].L==c[t].R)
{
c[t].max = a[c[t].L];
c[t].min = a[c[t].L];
return ;
}
bulid(t*2,i,(int)(i+j)/2 );
bulid(t*2+1,(int)(i+j)/2+1,j);
c[t].max = ( c[t*2].max>c[t*2+1].max?c[t*2].max:c[t*2+1].max);
c[t].min = ( c[t*2].min<c[t*2+1].min?c[t*2].min:c[t*2+1].min);
}
void print(int x,int y,int t)
{
if(c[t].L>=x&&c[t].R<=y)//
{
if(c[t].max>l_max) l_max = c[t].max;
if(c[t].min<l_min) l_min = c[t].min;
return ;
}
int xx =(c[t].L+c[t].R)/2;
if(y<=xx)
{
print(x,y,t*2);
}
else if(x>=xx+1)
{
print(x,y,t*2+1);
}
else
{
print(x,xx,t*2);
print(xx,y,t*2+1);
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
memset(a,0,sizeof(a));
int i;
for( i = 1; i <= n; i++ )
{
scanf("%d",&a[i]);
}
bulid(1,1,n);
for(i = 1; i <= m; i++)
{
l_max = 0;
l_min = N*100;
int x,y;
scanf("%d%d",&x,&y);
print(x,y,1);
printf("%d\n",l_max-l_min);
}
return 0;
}