参考:http://blog.youkuaiyun.com/metalseed/article/details/8039326 线段树的讲解
#include<iostream>
using namespace std;
#define MAXN 50005
int min(int x,int y)
{
return x<y?x:y;
}
int max(int x,int y)
{
return x>y?x:y;
}
struct STreeNode
{
int left ,right;//left 结点的左端点
int maxv,minv; // 结点的值
};
STreeNode STree[MAXN*4]; //线段树节点个数
int a[MAXN],ansmax,ansmin;
//建立线段树
void build(int L ,int R ,int id)
{
//left,right分别为当前节点的左右端点,id为节点在数组中的编号
STree[id].left=L;
STree[id].right=R;
int mid=(L+R)/2;
if(L==R)
{
STree[id].maxv=STree[id].minv=a[L];
return;
}
//递归的建立左右子树
build(L,mid,id*2);
build(mid+1,R,id*2+1);
STree[id].maxv=max(STree[id*2].maxv,STree[id*2+1].maxv);
STree[id].minv=min(STree[id*2].minv,STree[id*2+1].minv);
}
void query(int left,int right,int id)
{
//当前结点完全包含于查询区间 [left,right]
if(left<=STree[id].left&&right>=STree[id].right)
{
ansmax=max(STree[id].maxv,ansmax);
ansmin=min(STree[id].minv,ansmin);
return;
}
int mid=(STree[id].left+STree[id].right)/2;
if(mid<left)
query(left,right,id*2+1);//只进入右子树
else if(mid>=right) query(left,right,id*2);//只左子树
else
{
query(left,right,id*2);
query(left,right,id*2+1);
}
}
int main()
{
int n,q,i,x,y;
while(scanf("%d%d",&n,&q)!=EOF)
{
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,n,1);
for(i=0;i<q;i++)
{
scanf("%d%d",&x,&y);
ansmax=-1; //注意初始化
ansmin=INT_MAX;
query(x,y,1);
// printf("%d %d\n",ansmax,ansmin);
printf("%d\n",ansmax-ansmin);
}
}
// system("pause");
return 0;
}