hdu - 4331 - Image Recognition - 掃描線

求在01圖中,以1爲邊的正方形有幾個。http://acm.hdu.edu.cn/showproblem.php?pid=4331

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#define lson l, m , rt << 1
#define rson m + 1, r , rt << 1 | 1
#define maxn 1010
int T, n, grid[maxn][maxn], d[maxn][maxn], u[maxn][maxn];
int r[maxn][maxn], c[maxn][maxn], sum[maxn << 2];
using namespace std;
void build(){
    memset(sum, 0, sizeof(sum));
}
void update(int pos, int l, int r, int rt){
    ++ sum[rt];
    if(l == r) return ;
    int m = (l + r) >> 1;
    if(pos <= m) update(pos, lson);
    else update(pos, rson);
}
int query(int pos, int l , int r, int rt){
    if(l == r) return sum[rt];
    int m = (l + r) >> 1;
    int ret = 0;
    if(pos <= m) ret += query(pos, lson) + sum[rt << 1 | 1];
    else if(pos > m) ret += query(pos, rson);
    return ret;
}
struct Data{
    int p, x;
}g[maxn * 2];
bool cmp(Data a, Data b){
    return a.p < b.p ||(a.p == b.p && a.x < b.x);
}

for(int i = n; i > 1; -- i){
    ans += solve(i, 1, n - i + 1);
}
for(int i = 1; i <= n; i ++){
    ans += solve(1, i, n - i + 1);
}
int solve(int xx, int yy, int n){
    int e = 0, m = 0, ret = 0;
    for(int k = 1, i = xx, j = yy; k <= n; k ++, i ++, j ++){
        if(grid[i][j]){
            g[m].p = k - u[i][j], g[m ++].x = -k;
            g[m].p = k, g[m ++].x = k;
        }
    }
    sort(g, g + m, cmp);
    build(); 
    for(int k = 1, i = xx, j = yy; k <= n; k ++, i ++, j ++){
        if(grid[i][j]){
            update(k + d[i][j] - 1, 1, n, 1);
        }
        while(e < m && g[e].p <= k){
            if(g[e].p == k){
                if(g[e].x < 0)
                    ret -= query(-g[e].x, 1, n, 1);
                else
                    ret += query(g[e].x, 1, n, 1);
            }
            ++ e;
        }
    }
    return ret ;
}
int main(){
    scanf("%d", & T);
    for(int ca = 1; ca <= T; ca ++){ 
        scanf("%d", &n);
        for(int i = 1; i <= n; i ++){
            for(int j =1 ; j <= n; j ++){
                scanf("%d", &grid[i][j]);
            }
        }
        memset(r, 0, sizeof(r));
        memset(c, 0, sizeof(c));
        for(int i = 1; i <= n; i ++){
            for(int j = 1; j <= n; j ++){
                if(grid[i][j]){
                    r[i][j] = r[i][j - 1] + 1;
                    c[i][j] = c[i - 1][j] + 1;
                    u[i][j] = min(r[i][j] , c[i][j]);
                }
            }
        }
        memset(r, 0, sizeof(r));
        memset(c, 0, sizeof(c));
        for(int i = n; i > 0; i --){
            for(int j = n; j > 0; j --){
                if(grid[i][j]){
                    r[i][j] = r[i][j + 1] + 1;
                    c[i][j] = c[i + 1][j] + 1;
                    d[i][j] = min(r[i][j] , c[i][j]);
                }
            }
        }
        int ans = 0;
        for(int i = n; i > 1; -- i){
            ans += solve(i, 1, n - i + 1);
        }
        for(int i = 1; i <= n; i ++){
            ans += solve(1, i, n - i + 1);
        }
        printf("Case %d: %d\n", ca, ans);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章