http://poj.org/problem?id=3264
这道题就是求一个区间的最大值与最小值的差,用的线段树做的。
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 5001000
using namespace std;
int a[maxn],x,y,N,Q,ans,max1,min1;
struct node
{
int l;
int r;
int tall;
int shorte;
}p[maxn];
void build_tree(int i,int l,int r)
{
p[i].l=l;
p[i].r=r;
if(l==r)
{
p[i].tall=a[l];
p[i].shorte=a[l];
return;
}
int mid=(l+r)/2;
build_tree(i+i,l,mid);
build_tree(i+i+1,mid+1,r);
p[i].tall=max(p[i+i].tall,p[i+i+1].tall);
p[i].shorte=min(p[i+i].shorte,p[i+i+1].shorte);
}
void search1(int i,int l,int r)
{
if(p[i].l==l&&p[i].r==r)
{
max1=max(max1,p[i].tall);
min1=min(min1,p[i].shorte);
return ;
}
int mid=(p[i].l+p[i].r)/2;
if(r<=mid)
{
search1(i+i,l,r);
}
else if(l>mid)
{
search1(i+i+1,l,r);
}
else
{
search1(i+i,l,mid);
search1(i+i+1,mid+1,r);
}
}
int main()
{
while(scanf("%d%d",&N,&Q)!=EOF)
{
for(int i=1; i<=N; i++)
{
scanf("%d",&a[i]);
}
build_tree(1,1,N);
for(int i=0; i<Q; i++)
{
max1=-1;
min1=maxn;
scanf("%d%d",&x,&y);
search1(1,x,y);
printf("%d\n",max1-min1);
}
}
return 0;
}
还有另外一种做法dp
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define maxn 500010
using namespace std;
int maxsum[maxn][30],a[maxn],N,Q,minsum[maxn][30],x,y;
int main()
{
while(scanf("%d%d",&N,&Q)!=EOF)
{
for(int i=1; i<=N; i++)
{
scanf("%d",&a[i]);
}
for(int i=1; i<=N; i++)
{
maxsum[i][0]=a[i];
minsum[i][0]=a[i];
}
int m=(int)(log(N*1.0)/log(2.0));
for(int j=1; j<=m; j++)
{
for(int i=1; i<=N; i++)
{
if(i+(1<<j)-1<=N)
{
maxsum[i][j]=max(maxsum[i][j-1],maxsum[i+(1<<(j-1))][j-1]);
minsum[i][j]=min(minsum[i][j-1],minsum[i+(1<<(j-1))][j-1]);
}
}
}
for(int i=0; i<Q; i++)
{
scanf("%d%d",&x,&y);
int k=(int)(log(y-x+1.0)/(log(2.0)));
printf("%d\n",max(maxsum[x][k],maxsum[y-(1<<k)+1][k])-min(minsum[x][k],minsum[y-(1<<k)+1][k]));
}
}
return 0;
}