数据结构:二维ST表
POJ2019
我们其实是很有必要把ST算法拓展到二维的,因为二维的RMQ问题还是不少的
int N,B,K;
int mm[];
int val[maxn][maxn];
int dpmin[maxn][maxn][][];
int dpmax[maxn][maxn][][];
这里的N是方阵的长宽,此处是正方形题目,然后mm是预处理出来的,方便计算指数
dpmin和dpmax就是预处理数组了
然后看一下开局预处理:
void initRMQ(int n,int m)
{
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
dpmin[i][j][][]=dpmax[i][j][][]=val[i][j];
for(int ii=;ii<=mm[n];ii++)
for(int jj=;jj<=mm[m];jj++)
if(ii+jj)
for(int i=;i+(<<ii)-<=n;i++)
for(int j=;j+(<<jj)-<=m;j++)
{
if(ii)
{
dpmin[i][j][ii][jj] = min(dpmin[i][j][ii-][jj],dpmin[i+(<<(ii-))][j][ii-][jj]);
dpmax[i][j][ii][jj] = max(dpmax[i][j][ii-][jj],dpmax[i+(<<(ii-))][j][ii-][jj]);
}
else
{
dpmin[i][j][ii][jj] = min(dpmin[i][j][ii][jj-],dpmin[i][j+(<<(jj-))][ii][jj-]);
dpmax[i][j][ii][jj] = max(dpmax[i][j][ii][jj-],dpmax[i][j+(<<(jj-))][ii][jj-]);
}
}
}
我们看预处理的时候还是比较明朗的,当然别忘了在主函数把mm初始化好
mm[]=-;
for(int i=;i<=;i++)
mm[i]=((i&(i-))==)?mm[i-]+:mm[i-];
然后就是求最大值和最小值的函数了,这里,一定要仔细地去写,很容易写错:
int rmq1(int x1,int y1,int x2,int y2) //max
{
int k1=mm[x2-x1+];
int k2=mm[y2-y1+];
x2=x2-(<<k1)+;
y2=y2-(<<k2)+;
return max(max(dpmax[x1][y1][k1][k2],dpmax[x1][y2][k1][k2]),max(dpmax[x2][y1][k1][k2],dpmax[x2][y2][k1][k2]));
}
int rmq2(int x1,int y1,int x2,int y2)
{
int k1=mm[x2-x1+];
int k2=mm[y2-y1+];
x2=x2-(<<k1)+;
y2=y2-(<<k2)+;
return min(min(dpmin[x1][y1][k1][k2],dpmin[x1][y2][k1][k2]),min(dpmin[x2][y1][k1][k2],dpmin[x2][y2][k1][k2]));
}
这个式子确实很长的
最后给出题目完整的实现:
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=;
int N,B,K;
int mm[];
int val[maxn][maxn];
int dpmin[maxn][maxn][][];
int dpmax[maxn][maxn][][];
void initRMQ(int n,int m)
{
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
dpmin[i][j][][]=dpmax[i][j][][]=val[i][j];
for(int ii=;ii<=mm[n];ii++)
for(int jj=;jj<=mm[m];jj++)
if(ii+jj)
for(int i=;i+(<<ii)-<=n;i++)
for(int j=;j+(<<jj)-<=m;j++)
{
if(ii)
{
dpmin[i][j][ii][jj] = min(dpmin[i][j][ii-][jj],dpmin[i+(<<(ii-))][j][ii-][jj]);
dpmax[i][j][ii][jj] = max(dpmax[i][j][ii-][jj],dpmax[i+(<<(ii-))][j][ii-][jj]);
}
else
{
dpmin[i][j][ii][jj] = min(dpmin[i][j][ii][jj-],dpmin[i][j+(<<(jj-))][ii][jj-]);
dpmax[i][j][ii][jj] = max(dpmax[i][j][ii][jj-],dpmax[i][j+(<<(jj-))][ii][jj-]);
}
}
}
int rmq1(int x1,int y1,int x2,int y2) //max
{
int k1=mm[x2-x1+];
int k2=mm[y2-y1+];
x2=x2-(<<k1)+;
y2=y2-(<<k2)+;
return max(max(dpmax[x1][y1][k1][k2],dpmax[x1][y2][k1][k2]),max(dpmax[x2][y1][k1][k2],dpmax[x2][y2][k1][k2]));
}
int rmq2(int x1,int y1,int x2,int y2)
{
int k1=mm[x2-x1+];
int k2=mm[y2-y1+];
x2=x2-(<<k1)+;
y2=y2-(<<k2)+;
return min(min(dpmin[x1][y1][k1][k2],dpmin[x1][y2][k1][k2]),min(dpmin[x2][y1][k1][k2],dpmin[x2][y2][k1][k2]));
}
int main()
{
mm[]=-;
for(int i=;i<=;i++)
mm[i]=((i&(i-))==)?mm[i-]+:mm[i-];
while(scanf("%d%d%d",&N,&B,&K)==)
{
for(int i=;i<=N;i++)
for(int j=;j<=N;j++)
scanf("%d",&val[i][j]);
initRMQ(N,N);
int x,y;
while(K--)
{
scanf("%d%d",&x,&y);
printf("%d\n",rmq1(x,y,x+B-,y+B-)-rmq2(x,y,x+B-,y+B-));
}
}
return ;
}
数据结构:二维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的值 第二行至 ...
- 模板 - 数据结构 - ST表 + 二维ST表
区间最大值,$O(nlogn)$ 预处理,$O(1)$ 查询,不能动态修改.在查询次数M显著大于元素数量N的时候看得出差距. 令 $f[i][j]$ 表示 $[i,i+2^j-1]$ 的最大值. 显然 ...
- [总结] 二维ST表及其优化
二维 \(\mathcal{ST}\) 表,可以解决二维 \(\mathcal{RMQ}\) 问题.这里不能带修改,如果要修改,就需要二维线段树解决了. 上一道例题吧 ZOJ2859 类比一维 \(\ ...
随机推荐
- 常用linux命令相关
[查看端口] netstat -tlnp netstat命令 netstat -an | grep 3306 3306替换成需要grep的端口号 lsof命令 通过list open file命令可以 ...
- mysql mariadb 密码设置
原文:https://my.oschina.net/uyunsky/blog/109532 一.初始安装 Method 1:在/usr/local/mysql/bin/下:./mysqladmin - ...
- 20145214 《Java程序设计》第6周学习总结
20145214 <Java程序设计>第6周学习总结 教材学习内容总结 串流设计 Java将输入/输出抽象化为串流,数据有来源及目的地,衔接两者的是串流对象. 输入串流代表对象为java. ...
- win8安装Ubuntu14
概述: 1.复制安装镜像和启动文件到FAT32分区 2.查找出FAT32分区的分区号,修改启动配置文件 3.启动FAT32分区的安装镜像,开始安装 UEFI Win7/8/Ubuntu 硬盘安装Ubu ...
- IIS10和Tomcat8整合
在网上找了很久,也试了很多,都没有弄好.后来根据这个博客,做一些小修小改,终于成功了. 我是从里面的IIS与TOMCAT整合那里开始看的.第一步上面要创建一个注册表,我没有创建.我是创建了一个名为&q ...
- C# 知识回顾 - 你真的懂异常(Exception)吗?
你真的懂异常(Exception)吗? 目录 异常介绍 异常的特点 怎样使用异常 处理异常的 try-catch-finally 捕获异常的 Catch 块 释放资源的 Finally 块 一.异常介 ...
- AutoResetEvent的基本用法
The following example uses an AutoResetEvent to synchronize the activities of two threads.The first ...
- ipython matplotlib
matplotlib实际上是一套面向对象的绘图库,它所绘制的图表中的每个绘图元素,例如线条Line2D.文字Text.刻度等在内存中都有一个对象与之对应.为了方便快速绘图matplotlib通过pyp ...
- mysql向上递归&向下递归
工作记录 向上递归函数test: BEGIN ); ); SET sTemp = '$'; SET sTempChd =cast(rid as CHAR); WHILE sTempChd is not ...
- [计算机网络-应用层] P2P应用
首先我们要先来区分一下下面的几种体系结构: CS:Client/Server 客户-服务器结构BS:Browser/Server 浏览器-服务器结构 P2P:Peer to Peer 对等结构 BS ...