求在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;
}