二維st表,一種暴力但卻快速的二維RMQ利器


先上例題:[HAOI2007]理想的正方形 大部分人都用單調隊列,但我不會。首先我們可以暴力枚舉所有的可能的正方形,每次我們需要查詢RMQ,如果用朴素的方法總復雜度就會變成N^4,你不T誰T

那怎么辦,總不可能寫正解吧,我們可以用二維st表,預處理N^2logN,每次O(1)查詢,N^2水過。

二維st表原理就是將一個正方形分成了4份:
令 st[i][j][k]表示左上角為i,j,邊長為k的正方形中的最大值。
sta[i][j][k]=Max(sta[i][j][k-1],sta[i+(1<<k-1)][j][k-1],sta[i][j+(1<<k-1)][k-1],sta[i+(1<<k-1)][j+(1<<k-1)][k-1]);

i,j,k-1:就是左上角那塊正方形,i+(1<<k-1),j,k-1,就是左下角那塊正方形,剩下兩塊就是另外兩個
查詢同理,將代碼放到編譯器中食用更佳

注意,強制類型轉換要用大括號括起要轉換的東西,例如 (int)(log(n)/log(2));

Code:

#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cmath>
using namespace std;
#define zmd main
int a,b,n;
int sta[1026][1026][12],sti[1026][1026][12];
int kk;
inline int query1(int x,int y,int xx,int yy)
{
	int t1=sta[x][y][kk],t2=sta[xx-(1<<kk)+1][y][kk],t3=sta[x][yy-(1<<kk)+1][kk],t4=sta[xx-(1<<kk)+1][yy-(1<<kk)+1][kk];
	return max(max(max(t1,t2),t3),t4);
}
inline int query2(int x,int y,int xx,int yy)
{
	int t1=sti[x][y][kk],t2=sti[xx-(1<<kk)+1][y][kk],t3=sti[x][yy-(1<<kk)+1][kk],t4=sti[xx-(1<<kk)+1][yy-(1<<kk)+1][kk];
	return min(min(min(t1,t2),t3),t4);
}
inline int Max(int a,int b,int c,int d)
{
	return max(max(max(a,b),c),d);
}
inline int Min(int a,int b,int c,int d)
{
	return min(min(min(a,b),c),d);
}
int zmd()
{
	std::cin>>a>>b>>n;
	for (int i=1;i<=a;++i) for (int j=1,tmp;j<=b;++j) {scanf("%d",&tmp);sta[i][j][0]=sti[i][j][0]=tmp;}
	int shit=min(a,b);
	for (int k=1;k<=11;++k)
		for (int i=1;i+(1<<k)-1<=a;++i)
			for (int j=1;j+(1<<k)-1<=b;++j)
			{
				sta[i][j][k]=Max(sta[i][j][k-1],sta[i+(1<<k-1)][j][k-1],sta[i][j+(1<<k-1)][k-1],sta[i+(1<<k-1)][j+(1<<k-1)][k-1]);
				sti[i][j][k]=Min(sti[i][j][k-1],sti[i+(1<<k-1)][j][k-1],sti[i][j+(1<<k-1)][k-1],sti[i+(1<<k-1)][j+(1<<k-1)][k-1]);
			}
	kk=(int)(log(n)/log(2));
	int ans=0x3f3f3f3f;
	for (int i=1;i+n-1<=a;i++)
	for (int j=1;j+n-1<=b;j++)
		ans=std::min(ans,query1(i,j,i+n-1,j+n-1)-query2(i,j,i+n-1,j+n-1));
	cout<<ans;
	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM