3235: [Ahoi2013]好方的蛇
分析:
可以求出以每个点为顶点的满足条件的矩形有多少个,单调栈求。设为sum。
然后对这个数组进行二维前缀和,可以求出每个矩阵内,以右下角、左下角为端点的矩形有多少个,分别设为f,g。
然后可以枚举一个点(x,y),计算有多少个矩形的左上角是这个点,然后分别计算x上面的矩形,和y左面的矩形,与它不相交。此时一个每个矩形都和它左上角右上角的矩形计算了两次,减去即可。
调来调去,最后发现模数多写了个0。。。
代码:
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> #include<cctype> #include<set> #include<queue> #include<vector> #include<map> using namespace std; typedef long long LL; inline int read() { int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; } const int mod = 10007, N = 1005; int a[N][N], f[N][N], g[N][N], u[N]; struct Node{ int x, sum, len; } sk[N]; char s[N]; int main() { int n = read(); for (int i = 1; i <= n; ++i) { scanf("%s", s + 1); for (int j = 1; j <= n; ++j) a[i][j] = s[j] == 'B'; } int top = 0, sum = 0, ans = 0; memset(u, 0, sizeof(u)); for (int k, i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) u[j] = a[i][j] ? u[j] + 1 : 0; top = sum = 0; for (int j = 1; j <= n; ++j) { k = 1; while (top && sk[top].x > u[j]) k += sk[top].len, sum -= sk[top--].sum; sk[++top] = (Node){u[j], u[j] * k, k}; sum += sk[top].sum - a[i][j]; f[i][j] = f[i - 1][j] + f[i][j - 1] - f[i - 1][j - 1] + sum; f[i][j] %= mod; sum += a[i][j]; } } memset(u, 0, sizeof(u)); for (int k, i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) u[j] = a[i][j] ? u[j] + 1 : 0; top = sum = 0; for (int j = n; j; --j) { k = 1; while (top && sk[top].x > u[j]) k += sk[top].len, sum -= sk[top--].sum; sk[++top] = (Node){u[j], u[j] * k, k}; sum += sk[top].sum - a[i][j]; g[i][j] = g[i - 1][j] + g[i][j + 1] - g[i - 1][j + 1] + sum; g[i][j] %= mod; sum += a[i][j]; } } memset(u, 0, sizeof(u)); for (int k, i = n; i; --i) { for (int j = 1; j <= n; ++j) u[j] = a[i][j] ? u[j] + 1 : 0; top = sum = 0; for (int j = n; j; --j) { k = 1; while (top && sk[top].x > u[j]) k += sk[top].len, sum -= sk[top--].sum; sk[++top] = (Node){u[j], u[j] * k, k}; sum += sk[top].sum - a[i][j]; ans += sum * f[n][j - 1] + sum * f[i - 1][n] - sum * f[i - 1][j - 1]; ans %= mod; sum += a[i][j]; } } memset(u, 0, sizeof(u)); for (int k, i = n; i; --i) { for (int j = 1; j <= n; ++j) u[j] = a[i][j] ? u[j] + 1 : 0; top = sum = 0; for (int j = 1; j <= n; ++j) { k = 1; while (top && sk[top].x > u[j]) k += sk[top].len, sum -= sk[top--].sum; sk[++top] = (Node){u[j], u[j] * k, k}; sum += sk[top].sum - a[i][j]; ans = (ans - sum * g[i - 1][j + 1] % mod + mod) % mod; sum += a[i][j]; } } cout << (ans + mod) % mod; return 0; }