zoukankan      html  css  js  c++  java
  • 士兵杀敌(三)

    题目描述

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

    时间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行

  • 相关阅读:
    uva 10491 Cows and Cars
    uva 10910 Marks Distribution
    uva 11029 Leading and Trailing
    手算整数的平方根
    uva 10375 Choose and divide
    uva 10056 What is the Probability?
    uva 11027 Palindromic Permutation
    uva 10023 Square root
    Ural(Timus) 1081. Binary Lexicographic Sequence
    扩展欧几里得(求解线性方程)
  • 原文地址:https://www.cnblogs.com/hpustudent/p/2129525.html
Copyright © 2011-2022 走看看