以POJ3264为例引入吧。其实还是很基础的线段树一种。这里不用修改,只要建树+查询即可了。但是我一开始用C++的输入输出流配套IO就tle了,换成C的scanf输入就ac了,还是挺卡时间的吧。但处理区间RMQ问题还是推荐ST表,因为ST表每次查询就O(1),但线段树的话,每次查询的话就是一个search过程,是O(logn)的复杂度,相比ST表劣势就出来了。不过这题数据范围给的小,线段树也能过。换成大一点的可能就TLE了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define endl '\n'
#define mem(a) memset(a,0,sizeof(a))
#define IO ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
ll input[500010];
struct node{
ll l,r,sum,lz,maxx,minn;
}tree[2000040];
int ans,n,m;
inline void build(ll i,ll l,ll r){
tree[i].l=l;tree[i].r=r,tree[i].lz=0;
if(l==r){
tree[i].sum=tree[i].maxx=tree[i].minn=input[l];
return ;
}
ll mid=(l+r)>>1;
build(2*i,l,mid);
build(2*i+1,mid+1,r);
tree[i].sum=tree[2*i].sum+tree[i*2+1].sum;
tree[i].maxx=max(tree[2*i].maxx,tree[2*i+1].maxx);
tree[i].minn=min(tree[2*i].minn,tree[2*i+1].minn);
}
inline ll searchmax(ll i,ll l,ll r){
if(tree[i].l>=l && tree[i].r<=r) //查max
return tree[i].maxx;
if(tree[i].r<l || tree[i].l>r) return 0;
ll s=0;
if(tree[i*2].r>=l) s=max(s,searchmax(i*2,l,r));
if(tree[i*2+1].l<=r) s=max(s,searchmax(i*2+1,l,r));
return s;
}
inline ll searchmin(ll i,ll l,ll r){
if(tree[i].l>=l && tree[i].r<=r) //查min
return tree[i].minn;
if(tree[i].r<l || tree[i].l>r) return 0;
ll s=INF;
if(tree[i*2].r>=l) s=min(s,searchmin(i*2,l,r));
if(tree[i*2+1].l<=r) s=min(s,searchmin(i*2+1,l,r));
return s;
}
int main(){
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++) scanf("%lld",&input[i]);
build(1,1,n);
while(m--){
ll l,r;
scanf("%lld%lld",&l,&r);
printf("%lld\n",searchmax(1,l,r)-searchmin(1,l,r));
}
}