3235: [Ahoi2013]好方的蛇

Posted mjtcn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3235: [Ahoi2013]好方的蛇相关的知识,希望对你有一定的参考价值。

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

 

以上是关于3235: [Ahoi2013]好方的蛇的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 3233[Ahoi2013]找硬币 ——搜索

[Ahoi2013]差异

[bzoj1966][Ahoi2005][VIRUS 病毒检测] (字符串dp)

luogu P4248 [AHOI2013]差异

AC日记——[Ahoi2013]作业 bzoj 3236

BZOJ3236:[AHOI2013]作业——题解