zoukankan      html  css  js  c++  java
  • Luogu P1440 求m区间内的最小值

    # 这题可以用RMQ(ST表)做!

    由于本题数据的特殊性,需要查找的区间的元素个数大部分是一样的(除了输出的前$m$行元素个数不足$m$个的情况),我们就可以把ST表(代码中$a$数组)进行降维攻击(雾)!这样一来使用RMQ(ST表)就不会MLE了!

    在时间方面,我们可以拿个变量(代码中$power$)存储$2$的$j$次方,这样就不需要每一步都进行位运算了,这样做竟把超时的一个点卡过去了……

    时空问题都解决了,接下来只要和一般的RMQ(ST表)进行相同的操作就可以了。


    但我们似乎忽略了一个问题……

    就是输出的前$m$行元素个数不足$m$个时,我们要从第一个元素开始找,元素个数肯定不到$m$个。但最后因降过维,我们只能输出元素个数为$m$的区间的最小值,这下应该怎么办呢?

    这时我们可以想到,区间元素个数小于$m$时是在倍增预处理的时候,这时的ST表还未定型,在中途过程中会出现我们需要的答案,所以这部分的答案要在我们倍增的过程中输出。

    我们发现,倍增过程中的每一层要输出的答案个数是不同的:

    1. 第一个输出肯定为$0$,因为第一个数前是没有数的;

    2. 如果$m>1$,那么第二个输出肯定是第一个数,因为第二个数前面只有一个数;

    3. 我们手推一下可以发现,在建ST表的过程中,编号小于等于$2 imes power$的答案可以直接输出(当然仅限于编号小于$m$的数,即元素个数不足$m$个);

    4. 剩下的数就直接在ST表建好后按正常RMQ方法输出最小值就可以啦~


    pascal代码如下:

    uses math;//log2要用math库qwq
    var n,m,i,j,k,l,power:longint;
    a:array[0..2000000]of longint;
    begin
    readln(n,m);
    for i:=1 to n do
    read(a[i]);
    writeln(0);//情况1
    if m>1 then//情况2
    writeln(a[1]);
    k:=trunc(log2(m));
    l:=2;//l为当前应输出第l个答案
    power:=1;
    for j:=1 to k do//建ST表
    begin
    power:=power*2;
    for i:=1 to n-power+1 do
    a[i]:=min(a[i],a[i+power div 2]);
    while (l<=power*2)and(l<m) do//情况3
    begin
    writeln(min(a[1],a[l-power+1]));
    inc(l);
    end;
    end;
    for i:=1 to n-m do//情况4
    writeln(min(a[i],a[i+m-power]),' ');
    end.
  • 相关阅读:
    洛谷P1880 [NOI1995]石子合并 (区间dp
    洛谷P1012 拼数(水题 字符串
    洛谷P1071 潜伏者(水题
    微信《跳一跳》超高分攻略,轻松排行榜首
    StringUtilsd的isEmpty、isNotEmpty、isBlank、isNotBlank
    java.util.Properties类
    timer.scheduleAtFixedRate和timer.schedule的实验
    schedule() 和 scheduleAtFixedRate() 区别
    session和jsessionid有什么关系
    增加Xss过滤步骤
  • 原文地址:https://www.cnblogs.com/qbwhtc/p/7500781.html
Copyright © 2011-2022 走看看