2018 牛客多校第七场 J Sudoku Subrectangles

https://www.nowcoder.com/acm/contest/145/J

题意:给出一个字符矩阵,只包含大小写字母,问有多少个子矩阵为字符数独(任意一行或一列没有重复字符)。

思路:

先预处理每个点往下往右能到最远的距离

然后枚举每个点为左上角,找能完全覆盖的子矩阵有多少个

答案会爆int

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1010;
char s[maxn][maxn];
int flag[maxn];
int righ[maxn][maxn];
int down[maxn][maxn];
int a[maxn][maxn];
int n,m;
int main()
{
    ll ans=0;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",s[i]+1);
    }
    int cnt=0;
    int k;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cnt++;
            for(k=j;k<=min(j+51,m);k++)
            {
                if(flag[s[i][k]]==cnt)
                    break;
                flag[s[i][k]]=cnt;
            }
            righ[i][j]=k-j;
            cnt++;
            for(k=i;k<=min(i+51,n);k++)
            {
                if(flag[s[k][j]]==cnt)
                    break;
                flag[s[k][j]]=cnt;
            }
            down[i][j]=k-i;
        }
    }

    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            a[i][j]=down[i][j];
            int R=j+righ[i][j]-1;
            for(k=j+1;k<=R;k++)
                a[i][k]=min(a[i][k-1],down[i][k]);
            ans+=righ[i][j];
            int D=i+down[i][j]-1,now=j+righ[i][j]-1;
            for(k=i+1;k<=D;k++)
            {
                now=min(now,j+righ[k][j]-1);
                while(a[i][now]<k-i+1&&now>=j)
                    now--;
                if(now<j)break;
                ans=ans+now-j+1LL;
            }
        }
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/imzxww/article/details/81564092