数据结构:二维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 类比一维 \(\ ...
随机推荐
- [C++] in-class initializer
C++11 introduced serveral contructor-related enhancements including: Class member initializers Deleg ...
- HDU 5794 A Simple Chess dp+Lucas
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5794 A Simple Chess Time Limit: 2000/1000 MS (Java/O ...
- iOS开发自定义试图切换
CATransition *transition = [CATransition animation]; transition.duration = 1.0f; transition.timingFu ...
- thinkphp5学习记录一
1 使用composer安装 composer create-project topthink/think=5.0.* tpblog --prefer-dist 2 配置环境vim /usr/loca ...
- 第四章 持续集成jenkins工具使用之项目配置
1.1 创建项目 点击“新建”,输入项目名称,选择“构建一个自由风格的软件项目”,点击ok,项目创建完成. 1.2 配置项目 点击步骤1创建的项目,进入项目页面,如图: 点击“配置”,进入配置 ...
- 关于&$地址传递的练习
php默认为传值传递: 既: $a=10;$b=$a; //$b为10$a=+10; //$a 为20 echo $a.'和'.$b; # $a is 20 and $b is 10! 要是想变为地 ...
- C# 饼形图
原文链接:https://www.cnblogs.com/icyJ/archive/2012/10/08/Chart_Pie.html 需要实现的目标是: 1.将数据绑定到pie的后台数据中,自动生成 ...
- leetcode 整理
1.Two Sum 构造Comparator,KSum 这一类的问题最基本的一题, 解法: 先sort,然后双指针,头尾各一个.进行加逼找值. 对于其余的KSum最终是降次到2次. 如3Sum固定一个 ...
- [OS] 操作系统常考知识点
转自:http://jennica.space/2017/03/21/os-principle/ 大纲如下: 1.操作系统概述2.操作系统运行环境3.进程线程模型4.处理器调度5.同步机制6.存储模型 ...
- POJ1422:Air Raid——题解
http://poj.org/problem?id=1422 题目大意:n个点m条有向边,每条边只能走一次,往点上放人让他们走遍所有边,问至少要多少人. —————————————————————— ...