区间最大值,$O(nlogn)$ 预处理,$O(1)$ 查询,不能动态修改。在查询次数M显著大于元素数量N的时候看得出差距。

令 $f[i][j]$ 表示 $[i,i+2^j-1]$ 的最大值。

显然, $f[i][0]=a[i]$ 。

根据定义式,写出状态转移方程: $f[i][j]=max(f[i][j-1],f[i+2^{j-1}][j-1])$ 。

我们可以这么理解:将区间 $[i,i+2^j-1]$ 分成相同的两部分

中点即为 $(i+(i+2^j-1))/2=i+2^{j-1}-1/2$

所以 $[i,i+2^j-1]$ 可以分成 $[i,i+2^{j-1}-1]$ 和 $[i+2^j,i+2^j-1]$

对于每个询问 $[x,y]$ ,我们把它分成两部分 $f[x][s],f[y-2^s+1][s]$

其中 $s=log_2(y-x+1)$ ,虽然这两个区间有重叠,但是重叠不会影响区间的最大值

#include <bits/stdc++.h>
using namespace std;
#define ll long long const int MAXLOGN=;
const int MAXN=;
int a[MAXN+],f[MAXN+][MAXLOGN+1],Logn[MAXN+]; inline int read() {
char c=getchar();
int x=,f=;
while(c<''||c>'') {
if(c=='-')
f=-;
c=getchar();
}
while(c>=''&&c<='') {
x=x*+c-'';
c=getchar();
}
return x*f;
} void init() {
Logn[]=;
Logn[]=;
for(int i=; i<=MAXN; i++) {
Logn[i]=Logn[i/]+;
}
}
int main() {
init();
int n=read(),m=read();
for(int i=; i<=n; i++)
f[i][]=read();
for(int j=; j<=MAXLOGN; j++)
for(int i=; i+(<<j)-<=n; i++)
f[i][j]=max(f[i][j-],f[i+(<<(j-))][j-]);
for(int i=; i<=m; i++) {
int x=read(),y=read();
int s=Logn[y-x+];
printf("%d\n",max(f[x][s],f[y-(<<s)+][s]));
}
return ;
}

二维:

#include<bits/stdc++.h>
using namespace std;
#define MAXN 501
int n,m;
int rec[MAXN][MAXN];
char dp[MAXN][MAXN][][];
char dp1[MAXN][MAXN][][];
inline int maxm(int a,int b,int c,int d) {
if(a<b)
a=b;
if(a<c)
a=c;
if(a<d)
a=d;
return a;
}
inline int minm(int a,int b,int c,int d) {
if(b<a)
a=b;
if(c<a)
a=c;
if(d<a)
a=d;
return a;
}
void st() {
for(int k=; (<<k)<=n; k++)
for(int l=; (<<l)<=m; l++)
for(int i=; i+(<<k)-<=n; i++)
for(int j=; j+(<<l)-<=m; j++) {
if(!k&&!l) {
dp1[i][j][k][l]=dp[i][j][k][l]=rec[i][j];
} else if(k==) {
dp[i][j][k][l]=max(dp[i][j][k][l-],dp[i][j+(<<(l-))][k][l-]);
dp1[i][j][k][l]=min(dp1[i][j][k][l-],dp1[i][j+(<<(l-))][k][l-]);
} else if(l==) {
dp[i][j][k][l]=max(dp[i][j][k-][l],dp[i+(<<(k-))][j][k-][l]);
dp1[i][j][k][l]=min(dp1[i][j][k-][l],dp1[i+(<<(k-))][j][k-][l]);
} else {
dp[i][j][k][l]=maxm(dp[i][j][k-][l-],dp[i+(<<(k-))][j][k-][l-],
dp[i][j+(<<(l-))][k-][l-],dp[i+(<<(k-))][j+(<<(l-))][k-][l-]);
dp1[i][j][k][l]=minm(dp1[i][j][k-][l-],dp1[i+(<<(k-))][j][k-][l-],
dp1[i][j+(<<(l-))][k-][l-],dp1[i+(<<(k-))][j+(<<(l-))][k-][l-]);
}
//printf("dp[%d][%d][%d][%d]=%d\n",i,j,k,l,dp[i][j][k][l]);
}
}
int rmq2dmax(int x,int y,int x1,int y1) {
int k=;
while((x1-x+)>=(<<k))
k++;
k--;
int l=;
while((y1-y+)>=(<<l))
l++;
l--;
return maxm(dp[x][y][k][l],dp[x1-(<<k)+][y][k][l],
dp[x][y1-(<<l)+][k][l],dp[x1-(<<k)+][y1-(<<l)+][k][l]);
} int rmq2dmin(int x,int y,int x1,int y1) {
int k=;
while((x1-x+)>=(<<k))
k++;
k--;
int l=;
while((y1-y+)>=(<<l))
l++;
l--;
return minm(dp1[x][y][k][l],dp1[x1-(<<k)+][y][k][l],
dp1[x][y1-(<<l)+][k][l],dp1[x1-(<<k)+][y1-(<<l)+][k][l]);
} int main() {
int g;
scanf("%d%d%d",&n,&m,&g);
for(int i=; i<=n; i++) {
for(int j=; j<=m; j++) {
scanf("%d",&rec[i][j]);
}
}
st();
for(int l=min(n,m); l; l--) {
for(int i=; i<=n; i++) {
if(i+l->n)
break;
for(int j=; j<=m; j++) {
if(j+l->m)
break;
int t=rmq2dmax(i,j,i+l-,j+l-)-rmq2dmin(i,j,i+l-,j+l-);
if(t<=g){
printf("%d\n",l);
exit();
}
}
}
}
}

模板 - 数据结构 - ST表 + 二维ST表的更多相关文章

  1. [模板]二维ST表

    考试yy二维ST表失败导致爆零. 其实和一维的ST表很像... 也是设$f[i][j][p][q]$为以$(i, j)$为左上角,长为$2^p$,宽为$2^q$的矩形的最大值. 算法流程是先把每一行都 ...

  2. BZOJ3577:玩手机(最大流,二维ST表)

    Description 现在有一堆手机放在坐标网格里面(坐标从1开始),坐标(i,j)的格子有s_(i,j)个手机. 玩手机当然需要有信号,不过这里的手机与基站与我们不太一样.基站分为两种:发送站和接 ...

  3. BZOJ1047[HAOI2007]理想的正方形——二维ST表

    题目描述 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入 第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非 ...

  4. 【CodeForces】713 D. Animals and Puzzle 动态规划+二维ST表

    [题目]D. Animals and Puzzle [题意]给定n*m的01矩阵,Q次询问某个子矩阵内的最大正方形全1子矩阵边长.n,m<=1000,Q<=10^6. [算法]动态规划DP ...

  5. 【洛谷 P2216】 [HAOI2007]理想的正方形(二维ST表)

    题目链接 做出二维\(ST\)表,然后\(O(n^2)\)扫一遍就好了. #include <cstdio> #include <cstring> #include <a ...

  6. Codeforces 713D Animals and Puzzle(二维ST表+二分答案)

    题目链接 Animals and Puzzle 题意  给出一个1e3 * 1e3的01矩阵,给出t个询问,每个询问形如x1,y1,x2,y2 你需要回答在以$(x1, y1)$为左上角,$(x1, ...

  7. [HNOI2007] 理想正方形 二维ST表

    题目描述 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入输出格式 输入格式: 第一行为3个整数,分别表示a,b,n的值 第二行至 ...

  8. 二维 ST POJ 2019

    题目大意:给你一个n*n的矩阵,每次给你一个点(x,y),以其为左上角,宽度为b的矩阵中最小的数值和最大数值的差是多少?  一共k个询问. 思路:简单的二维st. 定义dp(i,j,k,L)表示以(i ...

  9. 数据结构:二维ST表

    POJ2019 我们其实是很有必要把ST算法拓展到二维的,因为二维的RMQ问题还是不少的 int N,B,K; ]; int val[maxn][maxn]; ][]; ][]; 这里的N是方阵的长宽 ...

随机推荐

  1. 九度OJ 1108:堆栈的使用 (堆栈)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:6705 解决:1974 题目描述: 堆栈是一种基本的数据结构.堆栈具有两种基本操作方式,push 和 pop.Push一个值会将其压入栈顶, ...

  2. Conditions in bash scripting (if statements)

    Shell中判断语句if中-z至-d的意思 - sunny_2015 - 博客园 https://www.cnblogs.com/coffy/p/5748292.html Conditions in ...

  3. Template Pattern

    1.Template模式解决的问题:对于某一个业务逻辑在不同的对象中有不同的细节实现,但是逻辑的框架是相同的.将逻辑框架放在抽象基类中,并定义好细节的接口,子类中实现细节.Template模式利用多态 ...

  4. mac10.10 打造Python多版本虚拟环境

    一.简介 1.在操作系统mac10.10(yosemite)中搭建Python多版本虚拟环境: 2.多版本虚拟环境包含三个含义: 在一个操作系统中安装多个版本的Python,不同版本可以随意切换,例如 ...

  5. Redis学习笔记(1):Redis的说明与安装

    Redis学习笔记(1):Redis说明的安装 说明 什么是Redis REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-va ...

  6. spring事件广播

    可参考:http://www.cnblogs.com/atyou/archive/2013/01/07/2850106.html 其中的类图更是精彩,现截至如下:

  7. [usaco2003feb]impster

    FJ再也不用野蛮的方式为自己的奶牛编号了.他用一个B(1<=B<=16)位二进制编码给每头奶牛编号,并刻在奶牛耳朵上的金属条上.奶牛希望自己给自己选择一个编码.于是,瞒着FJ,他们制造了一 ...

  8. Android中点击事件的处理解析及常见问题

          当我们手指按下时,Android采用层层传递-冒泡的方式处理点击事件.例如,现在公司来了个小项目,老板一看分配给经理做,经理一看分配给小组长,小组长一看好简单,分配给组员.如果在这个传递过 ...

  9. Java GET和POST请求

    从表面来看GET和POST请求: GET请求是在url后直接附上请求体,url和请求体之间用"?"分割,不同参数之间用"&"分隔,%XX中的XX为该符号 ...

  10. HTML5 实现文件拖放上传

    1. [图片] 5375acf5gw1dusqsscfksj.jpg ​2. [代码][HTML]代码 <!DOCTYPE html><html lang="en" ...