• 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;
    }
  • 相关阅读:
    [JLOI2015]管道连接
    [TJOI2015]旅游
    [TJOI2015]组合数学
    [CSP-S2019] 树上的数
    [NOI2020] 超现实树
    1:关于证书服务器
    vue:实现竖向滚动条效果并实现锚点定位跳转
    修改ElementUI的样式----vue如何控制步骤条steps圆圈的大小 data-v-
    PyCharm 查看变量值
    PyCharm 单步执行单步调试不能停到断点
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10469524.html
Copyright © 2020-2023  润新知