一维二维Sparse Table
写在前面:
记录了个人的学习过程,同时方便复习
- 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的更多相关文章
- 稳定排序nlogn之归并排序_一维,二维
稳定排序nlogn之归并排序_一维,二维 稳定排序:排序时间稳定的排序 稳定排序包括:归并排序(nlogn),基数排序[设待排序列为n个记录,d个关键码,关键码的取值范围为radix,则进行链式基数排 ...
- 基于ZXing.Net生成一维二维码
新阁教育-喜科堂付工原创 最近很多小伙伴对一维码.二维码比较感兴趣,今天主要给大家分享一个C#生成条形码和二维码的案例. C#作为一个高级语言,特点就是快! 我们使用的是开源库ZXing,ZXing是 ...
- oracle学习之路(四) ---------PL/SQL 表,二维数组(TABLE)
LOB类型 ORACLE提供了LOB (Large OBject)类型.用于存储大的数据对象的类型.ORACLE眼下主要支持BFILE, BLOB, CLOB 及 NCLOB 类型. NCLOB 存储 ...
- c++ 依据输入动态声明数组(一维,二维)
较早的编译器是不同意这样做的,所以一些书籍比方以Tc解说的书本都说数组的下标不能是变量.在vc6.0下亦是如此. 只是在一些较新的编译器如dev c++已经支持了,例如以下代码不会报错 #includ ...
- C# 链表去重 List 一维 二维 分别使用 Distinct() GroupBy() 方法
分别使用List中Distinct(),GroupBy()实现链表的去重. 1.先上效果: 一维链表中分别有元素“aa”,"bb",'aa','aa',"cc" ...
- java 数组基础学习(一维二维数组)
1.一维数组 1>静态初始化:数据类型[ ] 变量名 = {元素} 例:int[ ] arr = {1,2} 动态初始化:数据类型[ ] 变量名 = new数据类型[数据长度] 例:int[ ] ...
- 【VBA】利用Range声明Array(一维/二维)
[说明] B2开始到B?(中间不能有空格),定义一维数组Arr_approver() Dim R_sh As Worksheet Set R_sh = ThisWorkbook.Sheets(&quo ...
- Java中一维,二维数组的静态和动态初始化
今天我们要开始来讲讲Java中的数组,包括一维数组和二维数组的静态初始化和动态初始化 数组概述: 数组可以看成是多个相同类型数据的组合,对这些数据的统一管理; 数组变量属于引用数据类型,数组也可以看成 ...
- matlab学习——05插值和拟合(一维二维插值,拟合)
05插值和拟合 1.一维插值 (1) 机床加工零件,试用分段线性和三次样条两种插值方法计算.并求x=0处的曲线斜率和13<=x<=15范围内y的最小值. x0=[0 3 5 7 9 11 ...
随机推荐
- Openstack neutron 网络服务 (七)
引用: https://docs.openstack.org/ocata/zh_CN/install-guide-rdo/common/get-started-networking.html neut ...
- AttGAN: Facial Attribute Editing by Only Changing What You Want 论文阅读笔记和AttGan的pytorch代码实现
1.总体框架 上面的过程用详细描述即是 Test阶段: Train阶段: 由于我们无法得知编辑后的image,所以显而易见人脸属性编辑是一个无监督问题,而对于我们的xa需要获得关于b的属性,故利用at ...
- 【Java】运算符(算术、赋值、比较(关系)、逻辑、条件、位运算符)
运算符 文章目录 运算符 1. 算术运算符 2. 赋值运算符 3. 比较运算符 4. 逻辑运算符 5. 条件运算符 6. 位运算符 7. 运算符优先级 8. 运算符操作数类型说明 9.code 算术运 ...
- zabbix_server上的问题
不要写成127.0.0.1,要不然一直包zabbix agent没有启动.
- 【Linux】salt的cmd.script命令介绍
salt是一个很棒的自动化运维工具之一,常用的有cmd.run,今天介绍的是cmd.script 其实一眼就能看出这个命令是执行脚本的命令 具体操作如下: 1.将/etc/salt/master中的 ...
- 01-CentOS 8.1安装 Docker
官方参考地址:https://docs.docker.com/install/linux/docker-ce/centos/ 里面包含包下载地址:https://download.docker.com ...
- InnoDB的主键选择与插入优化
索引的存放方式MyISAM和InnoDB存储引擎在MySQL中,不同存储引擎对索引的实现方式是不同的,总结下MyISAM和InnoDB两个存储引擎的索引实现方式.MyISAM引擎使用B+Tree作为索 ...
- 全栈性能测试修炼宝典-JMeter实战笔记(二)
性能测试初体验 性能测试实质:利用工具去模拟大量用户操作来验证系统能够承受的负载情况,找出潜在的性能问题,分析并解决:找出系统性能变化趋势,为后续的扩展提供参考 测试分类 测试内容中,负载测试.压力测 ...
- 扩展PE头属性说明
CRC检测的算法就是checksum 以下是DllCharacteristics的参数说明
- 反向传播(Back Propagation)
反向传播(Back Propagation) 通常在设计好一个神经网络后,参数的数量可能会达到百万级别.而我们利用梯度下降去跟新参数的过程如(1).但是在计算百万级别的参数时,需要一种有效计算梯度的方 ...