洛谷P2216 [HAOI2007]理想的正方形(RMQ+枚举)

news/2024/5/18 22:07:39 标签: RMQ, 枚举

这道题可以用RMQ来做。
RMQ原本是对一个数列进行预处理,这里我们只需要对矩阵的每一行都进行一次预处理就好。然后枚举可能的所有的正方形,用RMQ查询这个正方形里面的最大值和最小值,不断更新最大值与最小值之差就好。

// luogu-judger-enable-o2
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
const int inf=1e9+5;		//inf记得开的大一点,否则会出错的
const int maxn=1e3+5;
int map[maxn][maxn];
int dp1[maxn][maxn][10],dp2[maxn][maxn][10];	//dp1记录最大值,dp2记录最小值

int min_(int x,int y)		//可以用algorithm头文件里的比较函数,但这里特意自己写了一个是防止超时(STL速度是比较慢的)
{
	return x<y? x:y;
}

int max_(int x,int y)
{
	return x>y? x:y;
}

int main()
{
	int a,b,n;
	scanf("%d%d%d",&a,&b,&n);
	for(int i=1;i<=a;++i)
		for(int j=1;j<=b;++j)
			scanf("%d",&map[i][j]);
	if(n==1)
	{
		printf("0\n");
		return 0;
	}
	for(int i=1;i<=a;++i)	//逐行预处理
	{
		for(int j=1;j<=b;++j)	dp1[i][j][0]=dp2[i][j][0]=map[i][j];
		for(int j=1;(1<<j)<=b;++j)
			for(int k=1;k+(1<<j)-1<=b;++k)
			{
				dp1[i][k][j]=max_(dp1[i][k][j-1],dp1[i][k+(1<<(j-1))][j-1]);
				dp2[i][k][j]=min_(dp2[i][k][j-1],dp2[i][k+(1<<(j-1))][j-1]);
			}
	}
	int ans=inf,k=0;
	while((1<<(k+1))<=n)	++k;
	for(int i=1;i<=a-n+1;++i)	//枚举正方形的左上顶点来枚举正方形
		for(int j=1;j<=b-n+1;++j)
		{
			int ma,mi,l,r;
			l=j; r=j+n-(1<<k);	
			ma=max_(dp1[i][l][k],dp1[i][r][k]);
			mi=min_(dp2[i][l][k],dp2[i][r][k]);
			for(int p=i+1;p<=i+n-1;++p)	//扫遍正方形的每一行
			{
				ma=max_(ma,max_(dp1[p][l][k],dp1[p][r][k]));
				mi=min_(mi,min_(dp2[p][l][k],dp2[p][r][k]));
			}
			ans=min_(ans,ma-mi);
		}
	printf("%d\n",ans);
	return 0;
}

http://www.niftyadmin.cn/n/942951.html

相关文章

bzoj 1911: [Apio2010]特别行动队

Description Input Output Sample Input 4 -1 10 -20 2 2 3 4 Sample Output 9HINT 斜率优化DP 首先我们考虑初始转移方程f[i]max(f[j]a*(s[i]-s[j])^2b*(s[i]-s[j])c);其中s为x的前缀和 考虑j>k的时候j比k优 那么有f[j]a*(s[i]-s[j])^2b*(s[i]-s[j])c<f[k]a*(s[i]-s[k…

洛谷P2471 [SCOI2007]降雨量(RMQ)

我们可以对应输入顺序&#xff0c;为每个年份设置一个编号&#xff0c;用map来完成年份与编号之间的对应。接下来用RMQ算法查询即可。 但是这道题有很多的坑&#xff0c;没有仔细想清&#xff0c;很容易就出错。 正确的思路如下&#xff1a; 输入完n个年份a[n]&#xff0c;用ma…

bzoj 3437: 小P的牧场

Description 背景 小P是个特么喜欢玩MC的孩纸。。。 描述 小P在MC里有n个牧场&#xff0c;自西向东呈一字形排列&#xff08;自西向东用1…n编号&#xff09;&#xff0c;于是他就烦恼了&#xff1a;为了控制这n个牧场&#xff0c;他需要在某些牧场上面建立控制站&#xff0c;每…

POJ1330,Nearest Common Ancestors(LCA+RMQ/倍增/Tarjan)

LCA的裸题。LCA可以用三种方式求解&#xff0c;其中离线算法有Tarjan&#xff0c;在线算法有倍增&#xff0c;RMQ&#xff0c;个人觉得RMQ效率会高一点。 有个博客讲解的很好&#xff0c;链接&#xff1a; https://blog.csdn.net/my_sunshine26/article/details/72717112 这里我…

3097: Hash Killer I

Description 这天天气不错&#xff0c;hzhwcmhf神犇给VFleaKing出了一道题&#xff1a; 给你一个长度为N的字符串S&#xff0c;求有多少个不同的长度为L的子串。 子串的定义是S[l]、S[l 1]、... S[r]这样连续的一段。 两个字符串被认为是不同的当且仅当某个位置上的字符不同。…

POJ1986,Distance Queries(LCA)

这道题可以用LCA做出来&#xff0c;虽然最短路可以做出来&#xff0c;但是询问次数很多&#xff0c;每询问一次就求一次最短路的话&#xff0c;时间开销是很大的。 这里我是用LCA转化为RMQ求出来&#xff0c;需要注意的一点就是题所给的图可能不是连通的&#xff0c;所以在DFS的…

bzoj 3098: Hash Killer II

Description 这天天气不错&#xff0c;hzhwcmhf神犇给VFleaKing出了一道题&#xff1a; 给你一个长度为N的字符串S&#xff0c;求有多少个不同的长度为L的子串。 子串的定义是S[l]、S[l 1]、... S[r]这样连续的一段。 两个字符串被认为是不同的当且仅当某个位置上的字符不同。…

洛谷P1736 创意吃鱼法(DP)

题意大概就是要从一个n * m的矩阵当中&#xff0c;求出一个主对角线或者副对角线都是1&#xff0c;其它地方都是0的最大正方形&#xff0c;并输出它的边长。 最暴力的方法应该就是枚举&#xff0c;对于任何一点(i , j)&#xff0c;枚举它作为正方形的左上顶点/右上顶点时&#…