先解释一下线段树的概念。
用数组模拟树,每个元素储存一段数据信息。
用递归生成。
常用来求解区间最值和区间和(区间和也可用前缀和)。
(笔者在poj 3264上尝试了未通过,可能还需要优化,有时间再搞)
此处给出对该题的尝试结果。
然后直接上代码,看注释。
#include<iostream>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
using namespace std;
typedef struct node{
int l;//区间左端点
int r;//区间右端点
int maxx;
int minn;//区间最值
}node;
node a[400000];
int b[100000];
void build(int l,int r,int i)
{
a[i].l=l;
a[i].r=r;
if(l==r)//如果是单点
{
a[i].l=a[i].r=l;
a[i].maxx=a[i].minn=b[l];
return;
}
int mid=(l+r)/2;//求中点
build(l,mid,i<<1);//向左递归
build(mid+1,r,i<<1|1);//向右递归
a[i].maxx=max(a[i<<1].maxx,a[i<<1|1].maxx);//更新当前段
a[i].minn=min(a[i<<1].minn,a[i<<1|1].minn);
return;
}
int maxxx;//整体最值,此处用了全局变量也可以用返回值
int minnn;
void find(int x,int y,int i)
{
if(x==a[i].l&&y==a[i].r)
{
maxxx=max(maxxx,a[i].maxx);//更新全局变量
minnn=min(minnn,a[i].minn);
return;
}
int mid=(a[i].l+a[i].r)>>2;
if(x>mid)
{
find(x,y,i<<1|1);//向右找
}
else if(y<=mid)
{
find(x,y,i<<1);//向左找
}
else
{
find(x,mid,i<<1);//向左找
find(mid+1,y,i<<1|1);//向右找
}
}
int main()
{
int n,m;
cin>>n>>m;//n个元素,m次询问
for(int i=1;i<=n;i++)
{
cin>>b[i];
}
build(1,n,1);
int askx,asky;
for(int i=0;i<m;i++)
{
cin>>askx>>asky;
maxxx=0;
minnn=1e9+7;//一个很大的数
find(askx,asky,1);
cout<<maxxx-minnn<<endl;
}
}