二维单调队列或st表

模板题 :[HAOI2007]理想的正方形
题目链接:https://www.luogu.com.cn/problem/P2216
二维st表或二维单调队列。
单调队列做法:
Code:

#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int a,b,n,num[N][N],q[N],fnmx[N][N],fnmn[N][N];
int datmin[N][N],datmax[N][N],fucker[N],ans=INT_MAX;
void solve1(int x){
	int l=1,r=0,*c=num[x];
	for(int i=1;i<=b;i++){
		while(l<=r&&c[i]<c[q[r]])r--;
		q[++r]=i;
		while(l<=r&&i-q[l]>=n)l++;
		if(i>=n)datmin[x][i]=c[q[l]];
	} 
	return;
}
void solve2(int x){
	int l=1,r=0,*c=num[x];
	for(int i=1;i<=b;i++){
		while(l<=r&&c[i]>c[q[r]])r--;
		q[++r]=i;
		while(l<=r&&i-q[l]>=n)l++;
		if(i>=n)datmax[x][i]=c[q[l]];
	}
	return;
}
void solve3(int x){
	int l=1,r=0;
	for(int i=1;i<=a;i++)
		fucker[i]=datmax[i][x];
	for(int i=1;i<=a;i++){
		while(l<=r&&fucker[i]>fucker[q[r]])r--;
		while(l<=r&&i-q[l]>=n)l++;
		q[++r]=i;
		if(i>=n)fnmx[i][x]=fucker[q[l]];
	}
	return;	
}
void solve4(int x){
	int l=1,r=0;
	for(int i=1;i<=a;i++)
		fucker[i]=datmin[i][x];
	for(int i=1;i<=a;i++){
		while(l<=r&&fucker[i]<fucker[q[r]])r--;
		while(l<=r&&i-q[l]>=n)l++;
		q[++r]=i;
		if(i>=n)fnmn[i][x]=fucker[q[l]];
	}
	return;	
} 
int main(){
	scanf("%d%d%d",&a,&b,&n);
	for(int i=1;i<=a;i++)
		for(int j=1;j<=b;j++)
			scanf("%d",&num[i][j]);
	for(int i=1;i<=a;i++)solve1(i),solve2(i);
	for(int i=b;i>=n;i--)solve3(i),solve4(i);
	for(int i=1;i<=a;i++)
		for(int j=1;j<=b;j++)
			if(fnmx[i][j]&&fnmn[i][j])ans=min(fnmx[i][j]-fnmn[i][j],ans);
	printf("%d",ans);
	return 0;
}

二维st表:

#include<bits/stdc++.h>
using namespace std;
const int INF=2147483647,N=1e3+5;
int n,m,k,K,grid[N][N],dv[N][N],xv[N][N];
int query(int x, int y){
    int mx=0,mn=0;
    mx=max(dv[x][y],max(dv[x+k-(1<<K)][y+k-(1<<K)],max(dv[x+k-(1<<K)][y],dv[x][y+k-(1<<K)])));
    mn=min(xv[x][y],min(xv[x+k-(1<<K)][y+k-(1<<K)],min(xv[x+k-(1<<K)][y],xv[x][y+k-(1<<K)])));
    return mx-mn;
}
int main (){
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            scanf("%d",&grid[i][j]);
            dv[i][j]=xv[i][j]=grid[i][j];
        }    	
	K=floor(log2(k));
    for(int s=0;s<=K-1;s++)
        for(int i=1;i+(1<<s)<=n;i++)
            for(int j=1;j+(1<<s)<=m;j++){
                dv[i][j]=max(dv[i][j],max(dv[i+(1<<s)][j+(1<<s)],max(dv[i+(1<<s)][j],dv[i][j+(1<<s)])));
                xv[i][j]=min(xv[i][j],min(xv[i+(1<<s)][j+(1<<s)],min(xv[i+(1<<s)][j],xv[i][j+(1<<s)])));	
	        }
    int ans=INF;
    for(int i=1;i<=n-k+1;i++)
        for(int j=1;j<=m-k+1;j++)ans=min(ans,query(i,j));
	printf("%d\n",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/Xxhdjr/p/13419580.html