zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    初拾Java(问题一:404错误,页面找不到)
    新年新气象--总结过去,展望未来
    接口测试[整理]
    [转]SVN-版本控制软件
    浅谈黑盒测试和白盒测试
    Bug管理工具的使用介绍(Bugger 2016)
    P2805/BZOJ1565 [NOI2009]植物大战僵尸
    近期学习目标
    P3643/BZOJ4584 [APIO2016]划艇
    P5344 【XR-1】逛森林
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10469524.html
Copyright © 2011-2022 走看看