4817. 【NOIP2016提高A組五校聯考4】square

Description

Input

Output

Sample Input

3 4
1 1 0 1
0 1 1 0
0 1 1 0
5
1 1 2 3
2 1 3 2
3 2 3 4
1 1 3 4
1 2 3 4

Sample Output

1
1
1
2
2

Data Constraint

Solution

算法 1: 對於每個詢問,枚舉右下端點,並且枚舉答案,判斷是否合法。 時間複雜度O( ) 3 Tn 能通過第 1 個測試點。 可以 2 n 求出以(i,j)爲右下角的最大正方形邊長。 具體來說就是, 算法 2: 把算法 1 的枚舉答案改成二分答案。 時間複雜度 ( log) 2 O Tn 能通過第 1,2,3 數據點。 算法 3: 維護 g[i][j][k]表示 f[i][j-k]到 f[i][j]的最大值。 那麼預處理時間複雜度爲 ( ) 3 O n ,詢問時間複雜度爲O(Tnlog) 空間複雜度 ( ) 3 O n 能夠通過第 1,2,3,6,7 號數據點。 算法 4: 維護 g[i][j][k]表示 f[i][j- k 2 ]到 f[i][j]的最大值。 那麼預處理時間複雜度爲 ( log) 2 O n ,詢問時間複雜度爲O(Tnlog) 能夠通過第 1,2,3,6-7,12-13 號數據點。 還是二分答案,假如當前二分值爲 mid,其實只要判斷在 (x1+mid-1,y1+mid-1)~(x2,y2)這個矩形空間裏面是否存在 f 值大於 等於 mid 算法 5: 用樹套樹來維護矩形空間 f 的最大值。 預處理時間複雜度爲 ( log ) 2 2 O n ,詢問時間複雜度爲 ( log ) 3 O T 能夠通過第 1-3,6-11 號數據點。 算法 6: g[k][l][i][j]表示(i,j)到(i+k-1,j+l-1)這個矩形區域裏 f 的最大值是多少。 這樣的話每次二分判斷就是O(1) 的。 預處理時間複雜度爲 ( ) 4 O n ,詢問時間複雜度爲O(T log) 可以通過第 1-5 號數據點。 算法 7: 對於特殊的 m<=5 的測試點。 易得答案<=5,每個詢問枚舉答案,然後可以O(m)回答。 具體來說就是用 g[i][j][k]表示從(1,1)到(i,j)有多少個 f 值=k。 矩形減一下就可以判斷是否可行。 時間複雜度 ( ) 2 O Tm 能夠通過第 14-16 號測試點。 算法 8: 基於算法 6 的思路。 我們可以把 g 的設法改一改。 g[k][l][i][j]表示(i,j)到(i+2 k-1,j+2 l-1)這個矩形區域裏 f 的最大值是多 少。 這個就是二維 rmq。 這個預處理是 ( log ) 2 2 O n 的,每次回答是否可行是O(1) 的,所以詢 問時間複雜度爲O(T log) 能夠通過所有數據點。 常數優化技巧: 設狀態要設 g[k][l][i][j],如果是[i][j]在前面,預處理時間會更長。 因爲前一種設法,預處理時訪問的內存位置更接近。

 

 

題意:讓你求若干個給定區間中所包含的最大子正方形的邊長。

考場打了個暴力15分。

正解是二維RMQ。

我們可以設f[i][j]表示以(i,j)爲右下角的最大的矩形邊長。

則f[i][j]=0(if a[i][j]==0 ) min( f [ i-1 ][ j ],f [ i ][ j-1 ],f [ i-1 ][ j-1 ] )+1 (if a[i][j]==1 )

然後設g[ k ][ l ][ i ][ j ]表示從(i,j)這個點往下連續的2^k行連續2^l列中f[ i ][ j ]的最大值。

那麼對於每個給定區間,只需二分答案,再用二維RMQ,O(1)判斷答案是否可行即可。

時間複雜度O(T log)。

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<cmath>
#define I register int
#define ll long long
#define F(i,a,b) for(I i=a;i<=b;i++)
#define Fd(i,a,b) for(I i=a;i>=b;i--)
#define mem(a,b) memset(a,b,sizeof(a))
#define N 1001
using namespace std;
inline int rd()
{
	char c;I d=1,f=0;
	while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
	while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
	return d*f;
}
int n,m,f[N][N],g[10][10][N][N],ans,t,l,r,l1,l2,t1,t2,mid,lg[N]={0,0,1},p[11]={1,2,4,8,16,32,64,128,256,512,1024};
inline int max(I a,I b){return a>b?a:b;}
inline int min(I a,I b){return a<b?a:b;}

inline int check(I x1,I y1,I x2,I y2){
	l1=lg[x2-x1+1],l2=lg[y2-y1+1],t1=p[l1],t2=p[l2];
 	return max(max(g[l1][l2][x1][y1],g[l1][l2][x2-t1+1][y1]),max(g[l1][l2][x1][y2-t2+1],g[l1][l2][x2-t1+1][y2-t2+1]));
}
int main(){
	freopen("square.in","r",stdin);
	freopen("square.out","w",stdout);
	n=rd(),m=rd();
	F(i,3,N-1) lg[i]=lg[i>>1]+1;
	F(i,1,n){
		F(j,1,m){
			f[i][j]=rd();
			if(f[i][j]) f[i][j]+=min(f[i][j-1],min(f[i-1][j-1],f[i-1][j]));
			g[0][0][i][j]=f[i][j];
		}
	}
	F(k,0,lg[n]){
		F(l,0,lg[m]) if(k+l){
			F(i,1,n-p[k]+1){
				F(j,1,m-p[l]+1){
					if(k) g[k][l][i][j]=max(g[k][l][i][j],max(g[k-1][l][i][j],g[k-1][l][i+p[k-1]][j]));
					if(l) g[k][l][i][j]=max(g[k][l][i][j],max(g[k][l-1][i][j],g[k][l-1][i][j+p[l-1]]));
				}
			}
		}
	}
	I x1,y1,x2,y2;
	t=rd();
	while(t--){
		x1=rd(),y1=rd(),x2=rd(),y2=rd();ans=0;
		l=0,r=min(x2-x1+1,y2-y1+1);
		while(l<=r){
			mid=l+r>>1;
			if(check(x1+mid-1,y1+mid-1,x2,y2)>=mid) l=(ans=mid)+1;
			else r=mid-1;
		}
		printf("%d\n",ans);
	}
	return 0;
}

作者:zsjzliziyang 
QQ:1634151125 
轉載及修改請註明 
本文地址:https://blog.csdn.net/zsjzliziyang/article/details/103604945

發佈了206 篇原創文章 · 獲贊 212 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章