JZOJ4817. square
2016-10-11 17:15
232 查看
题目大意
给定一个n×m的矩阵,其中有一些位置是障碍物。现在有T个询问,每个询问查询一个子矩阵中最大的无障碍正方形边长是多少。
Data Constraint
n,m≤1000,T≤1000000
题解
设f[i][j]表示以(i,j)为右下角,最大能取到的边长长度。显然f[i][j]=min(f[i−1][j],f[i][j−1],f[i−1][j−1])+1
然后对于每个询问,我们考虑二分答案。对于当前二分的答案,我们需要查询在一个二维区域内是否存在f的值大于等于当前答案。这个可以二维RMQ解决。
注意状态的表达可以优化寻址时间。
时间复杂度:O(T logn)
SRC
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> using namespace std ; #define N 1000 + 10 const int MAXN = 10 ; int a , Tab ; int f , g[MAXN][MAXN] ; int n , m , Q ; inline int Max( int x , int y ) { return x > y ? x : y ; } inline int Min( int x , int y ) { return x < y ? x : y ; } inline int Read() { int ret = 0 ; char ch = getchar() ; while ( ch < '0' || ch > '9' ) ch = getchar() ; while ( ch >= '0' && ch <= '9' ) ret = ret * 10 + ch - '0' , ch = getchar() ; return ret ; } inline void Write( int x ) { if ( x < 10 ) putchar( x + '0' ) ; else { Write( x / 10 ) ; putchar( x % 10 + '0' ) ; } } inline void Pre() { for (int i = 1 ; i <= 1000 ; i ++ ) Tab[i] = log(i) / log(2) ; for (int k = 0 ; k < MAXN ; k ++ ) { for (int l = 0 ; l < MAXN ; l ++ ) { if ( !k && !l ) continue ; for (int i = 1 ; i <= n ; i ++ ) { for (int j = 1 ; j <= m ; j ++ ) { if ( k ) { if ( g[k-1][l][i][j] > g[k][l][i][j] ) g[k][l][i][j] = g[k-1][l][i][j] ; if ( i - (1 << (k - 1)) > 0 && g[k-1][l][i-(1<<(k-1))][j] > g[k][l][i][j] ) g[k][l][i][j] = g[k-1][l][i-(1<<(k-1))][j] ; } if ( l ) { if ( g[k][l-1][i][j] > g[k][l][i][j] ) g[k][l][i][j] = g[k][l-1][i][j] ; if ( j - (1 << (l - 1)) > 0 && g[k][l-1][i][j-(1<<(l-1))] > g[k][l][i][j] ) g[k][l][i][j] = g[k][l-1][i][j-(1<<(l-1))] ; } } } } } } inline int Find( int x1 , int y1 , int x2 , int y2 ) { int k1 = Tab[x2-x1+1] ; int k2 = Tab[y2-y1+1] ; int ret = g[k1][k2][x2][y2] ; if ( g[k1][k2][x1+(1<<k1)-1][y1+(1<<k2)-1] > ret ) ret = g[k1][k2][x1+(1<<k1)-1][y1+(1<<k2)-1] ; if ( g[k1][k2][x1+(1<<k1)-1][y2] > ret ) ret = g[k1][k2][x1+(1<<k1)-1][y2] ; if ( g[k1][k2][x2][y1+(1<<k2)-1] > ret ) ret = g[k1][k2][x2][y1+(1<<k2)-1] ; return ret ; } int main() { freopen( "square.in" , "r" , stdin ) ; freopen( "square.out" , "w" , stdout ) ; n = Read() , m = Read() ; for (int i = 1 ; i <= n ; i ++ ) { for (int j = 1 ; j <= m ; j ++ ) { a[i][j] = Read() ; if ( !a[i][j] ) f[i][j] = 0 ; else { if ( f[i][j-1] < f[i-1][j] ) f[i][j] = f[i][j-1] ; else f[i][j] = f[i-1][j] ; if ( f[i-1][j-1] < f[i][j] ) f[i][j] = f[i-1][j-1] ; f[i][j] ++ ; } g[0][0][i][j] = f[i][j] ; } } Pre() ; Q = Read() ; for (int i = 1 ; i <= Q ; i ++ ) { int x1 = Read() , y1 = Read() , x2 = Read() , y2 = Read() ; int l = 0 , r = Min( y2 - y1 , x2 - x1 ) + 1 , ans = 0 ; while ( l <= r ) { int mid = (l + r) >> 1 ; if ( Find( x1 + mid - 1 , y1 + mid - 1 , x2 , y2 ) >= mid ) l = mid + 1 , ans = mid ; else r = mid - 1 ; } Write( ans ) ; putchar( '\n' ) ; } return 0 ; }
以上.
相关文章推荐
- JZOJ【4817】. 【NOIP2016提高A组五校联考4】square
- {题解}[jzoj4817]【NOIP2016提高A组五校联考4】square
- NOIP提高组【JZOJ4817】square
- 【JZOJ 4817】【NOIP2016提高组 五校联考4】square
- 【JZOJ4817】【NOIP2016提高A组五校联考4】square
- jzoj4817 Square
- 【JZOJ4817】square
- JZOJ 4817 【NOIP2016提高A组五校联考4】square
- [JZOJ4817]square
- JZOJ 4817. 【NOIP2016提高A组五校联考4】square
- JZOJ4817. 【NOIP2016提高A组五校联考4】square 二维rmq
- [GCJ] 2011 Round 1C Problem A Square Tiles & Problem C Perfect Harmony
- 【JZOJ 5382】 数列 口胡
- Oracle PL/SQL正则表达式之脱字符caret(^)与中括号square brankets([])的组合使用小例
- Jzoj4725 素数序列
- Blogger Favicon - 面对上载后不呈现和not a square image问题
- [JZOJ5439]【NOIP2017提高A组集训10.21】Fantasy
- HDU 1518 Square
- JZOJ 5410. 【NOIP2017提高A组集训10.22】小型耀斑
- Square走入艺术博览会以及农贸市场