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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章