题目意思就是查询区间的最大值与最小值的差;
最简单的线段树问题,代码中讲解;
#include <cstdio>
#include <math.h>
#include <iostream>
#include <algorithm>
#define lchild left,mid,root<<1 ///在这里宏定义是后面不想写那么多参数了
#define rchild mid+1,right,root<<1|1 ///在构建用到
using namespace std;
const int maxn=200005;
int Max[maxn<<2]; ///存最大值
int Min[maxn<<2]; ///存最小值
int n;
void push_up(int root) ///更新线段树节点
{
Max[root]=max(Max[root<<1],Max[root<<1|1]);
Min[root]=min(Min[root<<1],Min[root<<1|1]);
}
void build(int left,int right,int root) ///构建线段树
{
if(left==right)
{
int num;
scanf("%d",&num);
Max[root]=num;
Min[root]=num;
return ;
}
int mid=(left+right)>>1;
build(lchild); ///宏定义中定义的lchild
build(rchild);
push_up(root);
}
int query(int L,int R,int left,int right,int root) ///查区间的最大值
{
if(L<=left && R>=right) return Max[root];
int mid=(left+right)>>1;
int ret=0; ///这里一定要注意,ret的初始值问题,大了就w了
if(L<=mid)
{
ret=max(ret,query(L,R,lchild));
}
if(R>mid)
{
ret=max(ret,query(L,R,rchild));
}
return ret;
}
int querymin(int L,int R,int left,int right,int root) ///查区间的最小值
{
if(L<=left && R>=right) return Min[root];
int mid=(left+right)/2;
int ret=1000005; ///这里一定要注意,ret的初始值问题,小了就w了
if(L<=mid)
{
ret=min(ret,querymin(L,R,lchild));
//red=min(red,query(L,R,lchild))
}
if(R>mid)
{
ret=min(ret,querymin(L,R,rchild));
//red=min(red,query(L,R,rchild))
}
return ret;
}
int main()
{
int n,m;
while(~scanf("%d %d",&n,&m))
{
build(1,n,1);
int t1,t2;
for(int i=1;i<=m;i++)
{
scanf("%d %d",&t1,&t2);
printf("%d\n",query(t1,t2,1,n,1)-querymin(t1,t2,1,n,1)); ///直接输出区间内最大值减最小值
}
}
}
代码一定要自己敲一遍,否则真的以后还是不会;
文章评论