• #10119. 「一本通 4.2 例 1」数列区间最大值 & P1816 忠诚(ST算法)


    • https://loj.ac/problem/10119 & https://www.luogu.org/problemnew/show/P1816

    • 时间复杂度:O(nlogn)+O(m);(n为个数,m为问题数)

    • 思路:详见信息学奥赛一本通;

    1. 预处理:ST算法实际是DP;a[MAXN]存数,f[i][j](f[MAXN][21])表示a[i]~a[i+2的j次方-1]范围内最大值(即a[i]为起点连续2的j次方个数的最大值);从中间平均分成两部分,每部分元素刚好2的j-1次方个,即,f[i][j]分为f[i][j-1]和f[i+2的j-1次方][j-1]。故得到状态转移方程f[i][j]=max(f[i][j-1],f[i+2的j-1次方][j-1]),边界条件f[i][0]=a[i]

    2. 询问:询问[li,ri]间最大值(即max,最小值即min),先求出x满足2的x次方<=ri-li+1,那么区间[li,ri]=[li,li+2的x次方-1]∩[ri-2的x次方+1,ri],两个区间元素均为2的x次方个,所以[li,ri]最大值为max(f[li][x],f[ri-2的x次方+1][x])(∵有交集)。直接给表达式:k=log2(y-x+1);ans=max(f[x][k],f[y-2的k次方+1][k])

    3. 技巧(待证明):log2函数效率低,故可用O(N)递推预处理出1~N这N种区间长度各自对应的k值,具体操作:lg[d]数组表示log2d向下取整,则lg[d]=lg[d/2]+1;

    • 代码:最大值max最小值min

      #include<bits/stdc++.h>
      using namespace std;
      const int MAXN=1e6+2;
      int n,m;
      int a[MAXN],lg[MAXN],f[MAXN][21];
      int main(){
          cin>>n>>m;
          for(int i=1;i<=n;i++) scanf("%d",&a[i]); //存数
          lg[0]=-1;
          for(int i=1;i<=n;i++)
              f[i][0]=a[i],lg[i]=lg[i>>1]+1; //边界处理+技巧lg数组
          for(int i=1;i<=20;i++) //一般最大到2的20次方即可
            for(int j=1;j+(1<<i)-1<=n;j++) //j+(1<<i)-1<=n即区间边界不可超过n;1<<i即2的i次方 
              f[j][i]=max(f[j][i-1],f[j+(1<<i-1)][i-1]); //状态转移方程f[i][j]=max(f[i][j-1],f[i+2的j-1次方][j-1])
          int x,y;
          for(int i=1;i<=m;i++){
              scanf("%d%d",&x,&y);
              int s=lg[y-x+1]; //技巧lg数组 
              printf("%d
      ",max(f[x][s],f[y-(1<<s)+1][s])); //max(f[li][x],f[ri-2的x次方+1][x])(∵有交集) 
          }
          return 0;
      }
  • 相关阅读:
    UEFI和GPT
    EFI/UEFI BIOS 入门
    UEFI+GPT模式下的Windows系统中分区结构和默认分区大小及硬盘整数分区研究
    UEFI和Legacy及UEFI+Legacy启动的区别
    UEFI与MBR区别
    UI基础字典转模型
    UI基础九宫格
    UI基础UIView常见属性及方法
    UI基础控件UIButton
    OC中NSFileManager类 和 copy一些用法
  • 原文地址:https://www.cnblogs.com/songjian-jiansong/p/10318707.html
Copyright © 2020-2023  润新知