题目描述

解决方案一:用线段树解决,因为查询的是某区间的最值

时间1396   空间  5304  代码长度75
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
struct node
{
    int l,r,min,max;
};
const int N=100005;
int num[N];
#define L(x) (x<<1)
#define R(x) ((x<<1)+1)
#define M(x,y) ((x+y)>>1)
node tree[4*N];
int big,small;
//建立线段树,由于是某个区间并未涉及到单个点,我建立的是叶子节点区间长度为1,而不是到单个点的线段树

void build(int t,int l,int r)
{
    tree[t].l=l;
    tree[t].r=r;
    if(l+1==r)
    {
        if(num[l]>num[r]){tree[t].min=num[r];tree[t].max=num[l];}
        else {tree[t].min=num[l];tree[t].max=num[r];}
        return;
    } 
    int mid=M(l,r);
    build(L(t),l,mid);
    build(R(t),mid,r);
    tree[t].max=max(tree[L(t)].max,tree[R(t)].max);
    tree[t].min=min(tree[L(t)].min,tree[R(t)].min);
}
//查询操作很简单,看看这个区间的最大最小值就行了
void query(int t,int l,int r)
{
    if(tree[t].l>=l && tree[t].r<=r)
    {
        if(tree[t].max>big)big=tree[t].max;
        if(tree[t].min<small)small=tree[t].min;
        return;
    }
    int mid=M(tree[t].l,tree[t].r);
    if(r<=mid)query(L(t),l,r);
    else if(l>=mid)query(R(t),l,r);
    else 
    {
        query(L(t),l,mid);
        query(R(t),mid,r);
    }
}

int main()
{
    int i,n,q;
    scanf("%d%d",&n,&q);
    for(i=1;i<=n;i++)scanf("%d",num+i);
    build(1,1,n);
    int a,b;
    while(q--)
    {
        scanf("%d%d",&a,&b);
        big=-1,small=100000005;
      //考虑问题要全面,当a==b时,线段树是不适应的,因为我建立的线段树是[a,b],[b,c],应该列出来单独考虑,在这个地方两次没提交成功
        if(a==b)printf("0\n");,
        else
        {
           query(1,a,b);
          printf("%d\n",big-small);
         }
    }
   system("pause");
    return 0;
}
 
 解决方案二:rmq的st算法即sparse table
时间  904    空间:15852
 45行
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
using namespace std;
const int N=100000;

int stmax[N][20],stmin[N][20],d[20];

void init(int n)
{
    int i,j;
    d[0]=1;
    for(i=1;i<=20;i++)d[i]=d[i-1]<<1;
    for(i=1;i<=n;i++){
        scanf("%d",&stmax[i][0]);
        stmin[i][0]=stmax[i][0];
    }
    int len = int(log(n*1.0)/log(2.0));
    for(j=1;j<=len;j++)
      for(i=1;i<=n;i++)
      if(i+d[j]-1<=n)
      {
            stmax[i][j]=max(stmax[i][j-1],stmax[i+d[j-1]][j-1]);
            stmin[i][j]=min(stmin[i][j-1],stmin[i+d[j-1]][j-1]);
      }
}
void rmq(int q) //
{
    int x,y,len;
    while(q--)
    {
        scanf("%d%d",&x,&y);
        len=int(log(y-x+1.0)/log(2.0)); 
        printf("%d\n",max(stmax[x][len],stmax[y-d[len]+1][len]));
        printf("%d\n",min(stmin[x][len],stmin[y-d[len]+1][len]));
    }
}
int main(){
      int n, q;
      scanf("%d%d",&n,&q);
      init(n);
      rmq(q);      
    
   system("pause");
    return 0;
}

 

15852   代码长度:45行

posted on 2011-08-06 16:16  猿类的进化史  阅读(260)  评论(0编辑  收藏  举报