• NYOJ119 士兵杀敌(三) RMQ


     

    士兵杀敌(三)

    时间限制:2000 ms  |  内存限制:65535 KB
    难度:5
     
    描述

    南将军统率着N个士兵,士兵分别编号为1~N,南将军经常爱拿某一段编号内杀敌数最高的人与杀敌数最低的人进行比较,计算出两个人的杀敌数差值,用这种方法一方面能鼓舞杀敌数高的人,另一方面也算是批评杀敌数低的人,起到了很好的效果。

    所以,南将军经常问军师小工第i号士兵到第j号士兵中,杀敌数最高的人与杀敌数最低的人之间军功差值是多少。

    现在,请你写一个程序,帮小工回答南将军每次的询问吧。

    注意,南将军可能询问很多次。

     
    输入
    只有一组测试数据
    第一行是两个整数N,Q,其中N表示士兵的总数。Q表示南将军询问的次数。(1<N<=100000,1<Q<=1000000)
    随后的一行有N个整数Vi(0<=Vi<100000000),分别表示每个人的杀敌数。
    再之后的Q行,每行有两个正正数m,n,表示南将军询问的是第m号士兵到第n号士兵。
    输出
    对于每次询问,输出第m号士兵到第n号士兵之间所有士兵杀敌数的最大值与最小值的差。
    样例输入
    5 2
    1 2 6 9 3
    1 2
    2 4
    样例输出
    1
    7
    
      1 /* 
      2    功能Function Description:     NYOJ-119
      3    开发环境Environment:          DEV C++ 4.9.9.1
      4    技术特点Technique:
      5    版本Version:
      6    作者Author:                   可笑痴狂
      7    日期Date:                      20120815
      8    备注Notes:                    ------RMQ算法(O(1)的时间复杂度查询区间最值)
      9 */
     10 /*
     11 //代码一:过程中都是存的最值的下标
     12 #include<stdio.h>
     13 #define MAX_N 100000+5
     14 #define MAX_L 17  //2^17>100000
     15 //定义存储的都是下标
     16 int num[MAX_N];
     17 int minN[MAX_N][MAX_L],maxN[MAX_N][MAX_L];
     18 //maxN[i][j]存储的是从编号i开始的连续2^j个数中最大值的下标
     19 //minN[i][j]存储的是从编号i开始的连续2^j个数中最小值的下标
     20 int max(int i,int j)
     21 {
     22     return num[i]>num[j]?i:j;
     23 }
     24 
     25 int min(int i,int j)
     26 {
     27     return num[i]<num[j]?i:j;
     28 }
     29 
     30 void preST(int n)
     31 {
     32     int i,j;
     33     for(i=0;i<n;++i)      //初始时候 num[minN[i][0]]=num[maxN[i][0]]=num[i]
     34         minN[i][0]=maxN[i][0]=i;
     35     for(i=1;(1<<i)<=n;++i)
     36         for(j=0;j+(1<<i)-1<n;++j)
     37         {
     38             maxN[j][i]=max(maxN[j][i-1],maxN[j+(1<<(i-1))][i-1]);
     39             minN[j][i]=min(minN[j][i-1],minN[j+(1<<(i-1))][i-1]);
     40         }
     41 }
     42 
     43 int ST(int a,int b,int flag)
     44 {
     45     int pow;
     46     --a;         因为是从0号单元开始存的,所以都减一
     47     --b;
     48     for(pow=1;(1<<pow)<b-a+1;++pow);
     49     --pow;
     50     if(flag)   //返回最大值
     51         return num[max(maxN[a][pow],maxN[b-(1<<pow)+1][pow])];//因为前后两段有重叠,所以注意是从后边向前计算边界
     52     else      //返回最小值
     53         return num[min(minN[a][pow],minN[b-(1<<pow)+1][pow])];
     54 }
     55 
     56 int main()
     57 {
     58     int i,n,m,a,b;
     59     while(scanf("%d%d",&n,&m)!=EOF)
     60     {
     61         for(i=0;i<n;++i)
     62             scanf("%d",&num[i]);
     63         preST(n);
     64         for(i=0;i<m;++i)
     65         {
     66             scanf("%d%d",&a,&b);
     67             if(a>b)
     68             {
     69                 a^=b;
     70                 b^=a;
     71                 a^=b;
     72             }
     73             printf("%d\n",ST(a,b,1)-ST(a,b,0));
     74         }
     75     }
     76     return 0;
     77 }
     78 
     79   */
     80 
     81 //代码二:也可以直接存最值
     82 #include<stdio.h>
     83 #define MAX_N 100000+5
     84 #define MAX_L 17  //2^17>100000
     85 
     86 int num[MAX_N];
     87 int minN[MAX_N][MAX_L],maxN[MAX_N][MAX_L];
     88 
     89 int max(int i,int j)
     90 {
     91     return i>j?i:j;
     92 }
     93 
     94 int min(int i,int j)
     95 {
     96     return i<j?i:j;
     97 }
     98 
     99 void preST(int n)
    100 {
    101     int i,j;        
    102     for(i=1;(1<<i)<=n;++i)
    103         for(j=0;j+(1<<i)-1<n;++j)
    104         {
    105             maxN[j][i]=max(maxN[j][i-1],maxN[j+(1<<(i-1))][i-1]);
    106             minN[j][i]=min(minN[j][i-1],minN[j+(1<<(i-1))][i-1]);
    107         }
    108 }
    109 
    110 int ST(int a,int b,int flag)
    111 {
    112     int pow;
    113     --a;
    114     --b;
    115     for(pow=1;(1<<pow)<b-a+1;++pow);
    116     --pow;
    117     if(flag)   //返回最大值
    118         return max(maxN[a][pow],maxN[b-(1<<pow)+1][pow]);//因为前后两段有重叠,所以注意是从后边向前计算边界
    119     else      //返回最小值
    120         return min(minN[a][pow],minN[b-(1<<pow)+1][pow]);
    121 }
    122 
    123 int main()
    124 {
    125     int i,n,m,a,b;
    126     while(scanf("%d%d",&n,&m)!=EOF)
    127     {
    128         for(i=0;i<n;++i)
    129         {
    130             scanf("%d",&maxN[i][0]);
    131             minN[i][0]=maxN[i][0];
    132         }
    133         preST(n);
    134         for(i=0;i<m;++i)
    135         {
    136             scanf("%d%d",&a,&b);
    137             if(a>b)
    138             {
    139                 a^=b;
    140                 b^=a;
    141                 a^=b;
    142             }
    143             printf("%d\n",ST(a,b,1)-ST(a,b,0));
    144         }
    145     }
    146     return 0;
    147 }
    功不成,身已退
  • 相关阅读:
    SQLite常用SQL语句
    delphi设计浮动窗口
    在Delphi中使用键盘勾子获取键盘输入(译--5月7日)
    Delphi制作软键盘
    Delphi格式化输出函数(1): Format
    《你不知道的 CSS》之等比例缩放的盒子
    请用心练完这16个webpack小例子
    JavaScript高级内容笔记:原型链、继承、执行上下文、作用域链、闭包
    表格组件神器:bootstrap table详细使用指南
    玩转JavaScript正则表达式
  • 原文地址:https://www.cnblogs.com/dongsheng/p/2639930.html
Copyright © 2020-2023  润新知