写在前面:

  记录了个人的学习过程,同时方便复习

  • Sparse Table

  有些情况,需要反复读取某个指定范围内的值而不需要修改

  逐个判断区间内的每个值显然太浪费时间

  我们希望用空间换取时间

  ST表就是为此存在的

  在一维二维甚至三维中,利用动态规划的思想,将区域反复切割直到不能再分

  每一次切割产生的范围都可以存储想要的值:

    在生成时找好获得值的方法

    查询时找好获取值得关系

  在储存时,由于分割总是分成两半(横着来一下,竖着来一下就是四段)

  利用这个性质,就能高效的用2k或者2kn,2km表示每个分割区域的长度(面积)

  而在实现ST表的功能时,是将以上内容倒着进行的

  下面的代码仅仅是实现查询范围最大值

  若想查询范围最小值,对于二维的情况,可能会遇到一个矩阵没有填满的情况,取到了0

  这种情况需要特判一下

  同理,范围最大公因数,最小公倍数也需要特判

  但是最大值,差,和这种有没有多出来的0都一样的,就不必特判了

(这一点在二维的矩阵树里也有体现)

  一维Sparse Table,区间类动态规划

C++:

 1 #include<bits/stdc++.h>
2 #define re register
3
4 using namespace std;
5
6 const int MAXN=100010;
7 int n,f[MAXN][31],Ql,Qr;
8 //f[左端点][2^k]
9 //区间[左端点][左端点+2^k-1]
10
11 inline int C_max(int a,int b){return a>b? a:b;}
12
13 int RMQ(int l,int r){
14 int t=0;//需要一个t使得2^k>=(r-l+1),2^k<(r-l+1),即两个2^t长度能覆盖区间
15 while((1<<(t+1))<=(r-l+1)) t++;//直到2^(t+1)就比总长度还要大了
16 return C_max(
17 f[l ][t],
18 f[r-(1<<t)+1][t]
19 );
20 }
21
22 int main(int argc,char *argv[],char *enc[])
23 {
24 scanf("%d",&n);
25
26 for(re int i=1;i<=n;++i)
27 scanf("%d",&f[i][0]);
28
29 for(re int k=1;(1<<k)<=n;++k)
30 for(re int i=1;i+(1<<k)-1<=n;++i)
31 f[i][k]=C_max(//每段长度均为2^(k-1)
32 f[i ][k-1],
33 f[i+(1<<(k-1))][k-1]
34 );
35
36 while(scanf("%d%d",&Ql,&Qr)==2)
37 printf("%d\n",RMQ(Ql,Qr));
38
39 return 0;
40 }
41 /*
42 将区间
43 (i,i+2^k-1)分成
44
45 (i,i+2^(k-1)-1)
46 (i+2^(j-1),i+2^k-1)
47 两部分
48 */

Java:

 1 import java.io.*;
2 import java.util.*;
3
4 class pony{
5
6 static int MAXN=100010;
7 static int n,Ql,Qr;
8 static int[][] f=new int[MAXN][31];
9 //f[左端点][2^k]
10 //区间[左端点][左端点+2^k-1]
11
12 static int C_max(int a,int b){return a>b? a:b;}
13
14 static int RMQ(int l,int r){
15 int t=0;//需要一个t使得2^k>=(r-l+1),2^k<(r-l+1),即两个2^t长度能覆盖区间
16 while((1<<(t+1))<=(r-l+1)) t++;//直到2^(t+1)就比总长度还要大了
17 return C_max(
18 f[l ][t],
19 f[r-(1<<t)+1][t]
20 );
21 }
22
23 public static void main(String[] args) throws Exception {
24
25 Scanner cin=new Scanner(System.in);
26 n=cin.nextInt();
27
28 for(int i=1;i<=n;++i)
29 f[i][0]=cin.nextInt();
30
31 for(int k=1;(1<<k)<=n;++k)
32 for(int i=1;i+(1<<k)-1<=n;++i)
33 f[i][k]=C_max(//每段长度均为2^(k-1)
34 f[i ][k-1],
35 f[i+(1<<(k-1))][k-1]
36 );
37
38 Ql=cin.nextInt();
39 Qr=cin.nextInt();
40
41 System.out.println(RMQ(Ql,Qr));
42 }
43 }

  二维Sparse Table,矩阵类动态规划

C++:

 1 #include<bits/stdc++.h>
2 #define re register
3
4 using namespace std;
5
6 const int MAXN=1010,MAXM=1010;
7 int n,m,f[MAXN][MAXN][15][15],qx1,qy1,qx2,qy2;
8 //f[y1][x1][km][kn]
9 //矩阵(x1,y1)(x1+2^kn-1,y1+2^km-1)
10
11 inline int C_max(int a,int b){return a>b? a:b;}
12 int C_max4(int a,int b,int c,int d){return C_max(C_max(C_max(a,b),c),d);}
13
14 int RMQ(int x1,int y1,int x2,int y2){
15 int tm=0,tn=0;
16 while((1<<(tm+1))<=(y2-y1+1)) ++tm;
17 while((1<<(tn+1))<=(x2-x1+1)) ++tn;
18 return C_max4(
19 f[y1 ][x1 ][tm][tn],
20 f[y2-(1<<tm)+1][x1 ][tm][tn],
21 f[y1 ][x2-(1<<tn)+1][tm][tn],
22 f[y2-(1<<tm)+1][x2-(1<<tn)+1][tm][tn]
23 );
24 }
25
26 int main(int argc,char *argv[],char *enc[])
27 {
28 scanf("%d%d",&n,&m);
29
30 for(re int i=1;i<=m;++i)
31 for(re int j=1;j<=n;++j)
32 scanf("%d",&f[i][j][0][0]);
33
34 /*
35 当某一维长度为1时不好处理,单独拿出来处理
36 */
37
38 for(re int km=1;(1<<km)<=m;++km)
39 for(int i=1;i+(1<<km)-1<=m;++i)
40 for(int j=1;j<=n;++j)
41 f[i][j][km][0]=C_max(f[i][j][km-1][0],f[i+(1<<(km-1))][j][km-1][0]);
42
43 for(re int kn=1;(1<<kn)<=n;++kn)
44 for(int i=1;i<=m;++i)
45 for(int j=1;j+(1<<kn)-1<=n;++j)
46 f[i][j][0][kn]=C_max(f[i][j][0][kn-1],f[i][j+(1<<(kn-1))][0][kn-1]);
47
48 for(re int km=1;(1<<km)<=m;++km)
49 for(re int kn=1;(1<<kn)<=n;++kn)
50 for(re int i=1;i+(1<<km)-1<=m;++i)
51 for(re int j=1;j+(1<<kn)-1<=n;++j)
52 f[i][j][km][kn]=C_max4(//每次平分矩形,小矩形长度为2^(j-1),高为2^(i-1)
53 f[i ][j ][km-1][kn-1],
54 f[i+(1<<(km-1))][j ][km-1][kn-1],
55 f[i ][j+(1<<(kn-1))][km-1][kn-1],
56 f[i+(1<<(km-1))][j+(1<<(kn-1))][km-1][kn-1]
57 );
58
59 while(scanf("%d%d%d%d",&qx1,&qy1,&qx2,&qy2)==4)
60 printf("%d\n",RMQ(qx1,qy1,qx2,qy2));
61
62 return 0;
63 }
64 /*
65 将矩阵
66 (j ,i ,j+2^k-1 ,i+2^k-1 )分成
67
68 (j ,i ,j+2^(k-1)-1,i+2^(k-1)-1)
69 (j ,i+2^(k-1)-1,j+2^(k-1)-1,i+2^k-1 )
70 (j+2^(k-1),i ,j+2^k-1 ,i+2^(k-1)-1)
71 (j+2^(k-1),i+2^(k-1)-1,j+2^k-1 ,i+2^k-1 )
72 四部分
73 */

Java:

 1 import java.io.*;
2 import java.util.*;
3
4 class pony{
5
6 static int MAXN=1010,MAXM=1010;
7 static int n,m,qx1,qy1,qx2,qy2;
8 static int[][][][] f=new int[MAXN][MAXN][15][15];
9 //f[y1][x1][km][kn]
10 //矩阵(x1,y1)(x1+2^kn-1,y1+2^km-1)
11
12 static int C_max(int a,int b){return a>b? a:b;}
13 static int C_max4(int a,int b,int c,int d){return C_max(C_max(C_max(a,b),c),d);}
14
15 static int RMQ(int x1,int y1,int x2,int y2){
16 int tm=0,tn=0;
17 while((1<<(tm+1))<=(y2-y1+1)) ++tm;
18 while((1<<(tn+1))<=(x2-x1+1)) ++tn;
19 return C_max4(
20 f[y1 ][x1 ][tm][tn],
21 f[y2-(1<<tm)+1][x1 ][tm][tn],
22 f[y1 ][x2-(1<<tn)+1][tm][tn],
23 f[y2-(1<<tm)+1][x2-(1<<tn)+1][tm][tn]
24 );
25 }
26
27 public static void main(String[] args) throws Exception {
28
29 Scanner cin=new Scanner(System.in);
30 n=cin.nextInt();
31 m=cin.nextInt();
32
33 for(int i=1;i<=m;++i)
34 for(int j=1;j<=n;++j)
35 f[i][j][0][0]=cin.nextInt();
36
37 /*
38 当某一维长度为1时不好处理,单独拿出来处理
39 */
40
41 for(int km=1;(1<<km)<=m;++km)
42 for(int i=1;i+(1<<km)-1<=m;++i)
43 for(int j=1;j<=n;++j)
44 f[i][j][km][0]=C_max(f[i][j][km-1][0],f[i+(1<<(km-1))][j][km-1][0]);
45
46 for(int kn=1;(1<<kn)<=n;++kn)
47 for(int i=1;i<=m;++i)
48 for(int j=1;j+(1<<kn)-1<=n;++j)
49 f[i][j][0][kn]=C_max(f[i][j][0][kn-1],f[i][j+(1<<(kn-1))][0][kn-1]);
50
51 for(int km=1;(1<<km)<=m;++km)
52 for(int kn=1;(1<<kn)<=n;++kn)
53 for(int i=1;i+(1<<km)-1<=m;++i)
54 for(int j=1;j+(1<<kn)-1<=n;++j)
55 f[i][j][km][kn]=C_max4(//每次平分矩形,小矩形长度为2^(j-1),高为2^(i-1)
56   f[i ][j ][km-1][kn-1],
57   f[i+(1<<(km-1))][j ][km-1][kn-1],
58   f[i ][j+(1<<(kn-1))][km-1][kn-1],
59   f[i+(1<<(km-1))][j+(1<<(kn-1))][km-1][kn-1]
60   );
61
62 qx1=cin.nextInt();
63 qy1=cin.nextInt();
64 qx2=cin.nextInt();
65 qy2=cin.nextInt();
66
67 System.out.println(RMQ(qx1,qy1,qx2,qy2));
68 }
69 }

一维二维Sparse Table的更多相关文章

  1. 稳定排序nlogn之归并排序_一维,二维

    稳定排序nlogn之归并排序_一维,二维 稳定排序:排序时间稳定的排序 稳定排序包括:归并排序(nlogn),基数排序[设待排序列为n个记录,d个关键码,关键码的取值范围为radix,则进行链式基数排 ...

  2. 基于ZXing.Net生成一维二维码

    新阁教育-喜科堂付工原创 最近很多小伙伴对一维码.二维码比较感兴趣,今天主要给大家分享一个C#生成条形码和二维码的案例. C#作为一个高级语言,特点就是快! 我们使用的是开源库ZXing,ZXing是 ...

  3. oracle学习之路(四) ---------PL/SQL 表,二维数组(TABLE)

    LOB类型 ORACLE提供了LOB (Large OBject)类型.用于存储大的数据对象的类型.ORACLE眼下主要支持BFILE, BLOB, CLOB 及 NCLOB 类型. NCLOB 存储 ...

  4. c++ 依据输入动态声明数组(一维,二维)

    较早的编译器是不同意这样做的,所以一些书籍比方以Tc解说的书本都说数组的下标不能是变量.在vc6.0下亦是如此. 只是在一些较新的编译器如dev c++已经支持了,例如以下代码不会报错 #includ ...

  5. C# 链表去重 List 一维 二维 分别使用 Distinct() GroupBy() 方法

    分别使用List中Distinct(),GroupBy()实现链表的去重. 1.先上效果: 一维链表中分别有元素“aa”,"bb",'aa','aa',"cc" ...

  6. java 数组基础学习(一维二维数组)

    1.一维数组 1>静态初始化:数据类型[ ] 变量名 = {元素} 例:int[ ] arr = {1,2} 动态初始化:数据类型[ ] 变量名 = new数据类型[数据长度] 例:int[ ] ...

  7. 【VBA】利用Range声明Array(一维/二维)

    [说明] B2开始到B?(中间不能有空格),定义一维数组Arr_approver() Dim R_sh As Worksheet Set R_sh = ThisWorkbook.Sheets(&quo ...

  8. Java中一维,二维数组的静态和动态初始化

    今天我们要开始来讲讲Java中的数组,包括一维数组和二维数组的静态初始化和动态初始化 数组概述: 数组可以看成是多个相同类型数据的组合,对这些数据的统一管理; 数组变量属于引用数据类型,数组也可以看成 ...

  9. matlab学习——05插值和拟合(一维二维插值,拟合)

    05插值和拟合 1.一维插值 (1) 机床加工零件,试用分段线性和三次样条两种插值方法计算.并求x=0处的曲线斜率和13<=x<=15范围内y的最小值. x0=[0 3 5 7 9 11 ...

随机推荐

  1. MyBatis初级实战之五:一对一关联查询

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  2. 前端开发好帮手,eslint配置全知道

    eslint让人又爱又恨,原因在于它的默认配置非常严格,动则一个小提示就直接报错不给运行.而在开发调试的过程中,我们想时时得到运行效果,它的严格又很烦. 在安装eslint后,我们可以在package ...

  3. Centos7 虚拟机优化

    配置yum源 rm -f /etc/yum.repos.d/* curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/ ...

  4. 从零搭建一个IdentityServer——集成Asp.net core Identity

    前面的文章使用Asp.net core 5.0以及IdentityServer4搭建了一个基础的验证服务器,并实现了基于客户端证书的Oauth2.0授权流程,以及通过access token访问被保护 ...

  5. Centos 安装postgreSQL9.4.3

    rpm -ivh http://download.postgresql.org/pub/repos/yum/9.4/redhat/rhel-7.2-x86_64/pgdg-centos94-9.4-3 ...

  6. 华为三层交换机限制vlan段的指定端口

    屏蔽vlan 120这个段的ip的所有2333端口 [NTT_3L]int Vlanif 120 [NTT_3L-Vlanif120]dis this # interface Vlanif120 ip ...

  7. LoadRunner监控Centos和Ubuntu资源之服务器配置

    Centos 我用的版本是Centos6.8   首先更新源以及基础操作我就不说了,直接上步骤: Step 1 安装相关程序 执行命令:yum install inetd,这一步是为了安装rstatd ...

  8. 使用Python的pandas模块、mplfinance模块、matplotlib模块绘制K线图

    目录 pandas模块.mplfinance模块和matplotlib模块介绍 pandas模块 mplfinance模块和matplotlib模块 安装mplfinance模块.pandas模块和m ...

  9. Linux中LPC、RPC、IPC的区别

    其实这玩意儿就是纸老虎,将英文缩写翻译为中文就明白一半了. IPC:(Inter Process Communication )跨进程通信 这个概念泛指进程之间任何形式的通信行为,是个可以拿来到处套的 ...

  10. hive搜索报错

    在自己搭建的集群上执行hive搜索语句 select count(*) from ods_event_log where dt='2019-12-14' group by dt; 报错如下: Stat ...