[总结] 二维ST表及其优化
二维 \(\mathcal{ST}\) 表,可以解决二维 \(\mathcal{RMQ}\) 问题。这里不能带修改,如果要修改,就需要二维线段树解决了。
上一道例题吧 ZOJ2859
类比一维 \(\mathcal{ST}\) 表,我们定义数组 \(f[i][j][k][p]\) 表示从 \((i,j)\) 往下 \(2^k\) 个元素,往右 \(2^p\) 个元素的最值。
建表的话,同样类比一维 \(\mathcal{ST}\) 表,外层两个循环 \(\mathcal{k}\) 和 \(\mathcal{p}\) , 然后内层取最值就行了。要注意的是,\(\mathcal{k}\) 和 \(\mathcal{p}\) 要从 \(0\) 开始循环,因为一行或者一列的情况也要维护。
查询的话,就把一个大矩形分成四个小矩形覆盖住就好了。
空间复杂度 \(\mathcal{O(n^2log^2n)}\)代码在这里
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#define N 302
int n,T;
int val[N][N];
int f[N][N][9][9];
void prework(){
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
if(i==0 and j==0) continue;
for(int k=1;k<=n-(1<<i)+1;k++){
for(int p=1;p<=n-(1<<j)+1;p++){
if(i==0)
f[k][p][i][j]=std::min(f[k][p][i][j-1],f[k][p+(1<<j-1)][i][j-1]);
else
f[k][p][i][j]=std::min(f[k][p][i-1][j],f[k+(1<<i-1)][p][i-1][j]);
}
}
}
}
}
int query(int r1,int c1,int r2,int c2){
int k1=log2(r2-r1+1);
int k2=log2(c2-c1+1);
return std::min(f[r1][c1][k1][k2],std::min(f[r2-(1<<k1)+1][c1][k1][k2],std::min(f[r1][c2-(1<<k2)+1][k1][k2],f[r2-(1<<k1)+1][c2-(1<<k2)+1][k1][k2])));
}
void file(){
freopen("in.txt","r",stdin);
freopen("out2.txt","w",stdout);
}
signed main(){
//file();
scanf("%d",&T);
while(T--){
memset(f,0x3f,sizeof f);
scanf("%d",&n);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
scanf("%d",&val[i][j]),f[i][j][0][0]=val[i][j];
}
prework();
int q; scanf("%d",&q);
while(q--){
int r1,r2,c1,c2;
scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
printf("%d\n",query(r1,c1,r2,c2));
}
}
}
我们有一种把空间复杂度优化到 \(\mathcal {O(n^2logn)}\) 的方法,记 \(\mathcal{f[i][j][k]}\) 表示以点 \((i,j)\) 为左上角,边长为 \(\mathcal{2^k}\) 的正方形所要维护的最值。
考虑查询,设查询矩形的左上角和右下角坐标分别为 \((r1,c1)\) 和 \((r2,c2)\)。且假设 \(r2-r1>c2-c1\)。
因为我们维护的是一个正方形内的最值,所以不能 \(\mathcal{O(1)}\) 的查询。而是要这样
for(int i=r1;i<=r2-(1<<k1)+1;i++)
ans=min(ans,min(f[c1][i][k1],f[c2-(1<<k1)][i][k1]))
其实这样是能被一个宽度为 \(1\) 的长方形把查询复杂度卡成 \(O(n)\) 的,但毕竟空间复杂度小了一个 \(\mathcal{log}\) 倍,对于一些内存紧张的题目,这种做法还是能起到一定效果的。
下面是 \(\mathcal{ZOJ}\) \(2859\) 第二种做法的代码。
上一下两种方法的对比吧,大家自行比较选择。
第一种:
第二种:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#define N 302
int T;
int n;
int val[N][N];
int f[N][N][9];
void prework(){
for(int i=1;i<9;i++){
for(int k=1;k<=n-(1<<i)+1;k++){
for(int p=1;p<=n-(1<<i)+1;p++){
f[k][p][i]=std::min(f[k][p][i-1],std::min(f[k+(1<<i-1)][p][i-1],std::min(f[k][p+(1<<i-1)][i-1],f[k+(1<<i-1)][p+(1<<i-1)][i-1])));
}
}
}
}
int query(int r1,int c1,int r2,int c2){
int k1=log2(r2-r1+1);
int k2=log2(c2-c1+1);
if(k1==k2) return std::min(f[r1][c1][k1],std::min(f[r2-(1<<k1)+1][c1][k1],std::min(f[r1][c2-(1<<k1)+1][k1],f[r2-(1<<k1)+1][c2-(1<<k1)+1][k1])));
if(k1<k2){
int minp=0x3f3f3f3f;
for(int i=c1;i<=c2-(1<<k1)+1;i+=(1<<k1)) minp=std::min(minp,std::min(f[r1][i][k1],f[r2-(1<<k1)+1][i][k1]));
minp=std::min(minp,std::min(f[r1][c2-(1<<k1)+1][k1],f[r2-(1<<k1)+1][c2-(1<<k1)+1][k1]));
return minp;
}
int minp=0x3f3f3f3f;
for(int i=r1;i<=r2-(1<<k2)+1;i+=(1<<k2)) minp=std::min(minp,std::min(f[i][c1][k2],f[i][c2-(1<<k2)+1][k2]));
minp=std::min(minp,std::min(f[r2-(1<<k2)+1][c1][k2],f[r2-(1<<k2)+1][c2-(1<<k2)+1][k2]));
return minp;
}
void file(){
freopen("in.txt","r",stdin);
freopen("out1.txt","w",stdout);
}
signed main(){
//file();
scanf("%d",&T);
while(T--){
memset(f,0x3f,sizeof f);
scanf("%d",&n);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++) scanf("%d",&val[i][j]),f[i][j][0]=val[i][j];
}
prework();
/*for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
for(int k=0;k<9;k++) printf("i=%d,j=%d,k=%d,f=%d\n",i,j,k,f[i][j][k]);
}
}*/
int q; scanf("%d",&q);
while(q--){
int r1,r2,c1,c2;
scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
printf("%d\n",query(r1,c1,r2,c2));
}
}
return 0;
}
[总结] 二维ST表及其优化的更多相关文章
- BZOJ3577:玩手机(最大流,二维ST表)
Description 现在有一堆手机放在坐标网格里面(坐标从1开始),坐标(i,j)的格子有s_(i,j)个手机. 玩手机当然需要有信号,不过这里的手机与基站与我们不太一样.基站分为两种:发送站和接 ...
- BZOJ1047[HAOI2007]理想的正方形——二维ST表
题目描述 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入 第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非 ...
- 【CodeForces】713 D. Animals and Puzzle 动态规划+二维ST表
[题目]D. Animals and Puzzle [题意]给定n*m的01矩阵,Q次询问某个子矩阵内的最大正方形全1子矩阵边长.n,m<=1000,Q<=10^6. [算法]动态规划DP ...
- 【洛谷 P2216】 [HAOI2007]理想的正方形(二维ST表)
题目链接 做出二维\(ST\)表,然后\(O(n^2)\)扫一遍就好了. #include <cstdio> #include <cstring> #include <a ...
- Codeforces 713D Animals and Puzzle(二维ST表+二分答案)
题目链接 Animals and Puzzle 题意 给出一个1e3 * 1e3的01矩阵,给出t个询问,每个询问形如x1,y1,x2,y2 你需要回答在以$(x1, y1)$为左上角,$(x1, ...
- [模板]二维ST表
考试yy二维ST表失败导致爆零. 其实和一维的ST表很像... 也是设$f[i][j][p][q]$为以$(i, j)$为左上角,长为$2^p$,宽为$2^q$的矩形的最大值. 算法流程是先把每一行都 ...
- [HNOI2007] 理想正方形 二维ST表
题目描述 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入输出格式 输入格式: 第一行为3个整数,分别表示a,b,n的值 第二行至 ...
- hdu2888 二维ST表(RMQ)
二维RMQ其实和一维差不太多,但是dp时要用四维 /* 二维rmq */ #include<iostream> #include<cstring> #include<cs ...
- 数据结构:二维ST表
POJ2019 我们其实是很有必要把ST算法拓展到二维的,因为二维的RMQ问题还是不少的 int N,B,K; ]; int val[maxn][maxn]; ][]; ][]; 这里的N是方阵的长宽 ...
随机推荐
- Android开发学习之路--MAC下Android Studio开发环境搭建
自从毕业开始到现在还没有系统地学习android应用的开发,之前一直都是做些底层的驱动,以及linux上的c开发.虽然写过几个简单的app,也对android4.0.3的源代码做过部分的分析,也算入门 ...
- Mysql大量插入数据时SQL语句的优化
1) 对于Myisam类型的表,可以通过以下方式快速的导入大量的数据. ALTER TABLE tblname DISABLE KEYS; loading the data ALT ...
- Cocos2D将v1.0的tileMap游戏转换到v3.4中一例(五)
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 为了暂时不影响原来的cat移动方法,我们在CatSprite.m ...
- 刀片服务器和磁盘阵列卡(RAID)技术---永和维护
近期客户需要更换服务器,客户把买好的服务器送来了,原本感觉很小的一个服务器,可当我看到的时候是一个大个的又长又宽,类似机房服务器的那种,后来米老师给大致讲解一番:这个是刀片服务器. 刀片服务器是指在标 ...
- Hadoop-1.0.4伪分布安装与配置
1.采用伪分布模式安装 将hadoop-****.tar.gz复制到linux的/usr/local目录下. 2.解压,重命名 #tar -xzvf hadoop-1.0.4.ta ...
- CUDA程序的调试总结【不定时更新】
1 )CUDA的程序,经常犯,但是很难发现的一个错误就是同步问题. 描述下实例 for (k = 0; k < N; k+=BS) { sda[tx] = gda[tx+index]; __sy ...
- 有关uploadifive的使用经验(转:http://www.cnblogs.com/itBscs/p/4781786.html )
这段时间做了一个项目用到uploadifive上传控件,和uploadify不同,这个控件是基于HTML5的版本而不用支持falsh,因而移动端也可以使用. 整理用过的相关属性与方法: 属性 作 ...
- Socket层实现系列 — 信号驱动的异步等待
主要内容:Socket的异步通知机制. 内核版本:3.15.2 我的博客:http://blog.csdn.net/zhangskd 概述 socket上定义了几个IO事件:状态改变事件.有数据可读事 ...
- TCP的ACK确认系列 — 延迟确认
主要内容:TCP的延迟确认.延迟确认定时器的实现. 内核版本:3.15.2 我的博客:http://blog.csdn.net/zhangskd 延迟确认模式 发送方在发送数据包时,如果发送的数据包有 ...
- OpenCV空洞填充算法
讨论帖: http://bbs.csdn.net/topics/391542633 在Matlab下,使用imfill可以很容易的完成孔洞填充操作,感觉这是一个极为常用的方法,然而不知道为什么Op ...