Sudoku Subrectangles (数独矩阵个数)

本文介绍了一道ACM竞赛题目:求解n*m矩阵中,所有每行每列都没有重复字母的矩阵数量。通过使用单调栈记录每位置的可行范围,实现了高效计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题:牛客网暑期ACM多校训练营(第七场)

题意:
这里写图片描述
n*m矩阵,求多少个每行每列都没有重复字母(分大小写)的矩阵

解析:

对每一个位置记录下最高往上可以走多少,往左可以走多少,然后遍历每一列,维护一个从当前位置往左走的每个位置的上限的单调栈

代码:


#include<bits/stdc++.h>
using namespace std;

char M[1002][1002];int n,m;
long long ans=0;
int l[1002][1002];
int uu[1002][1002];
int vis[200];
int sta[100];
void init(){
    for(int i=1;i<=n;i++){
        memset(vis,0,sizeof(vis));
        for(int j=1;j<=m;j++){
            l[i][j]=min(l[i][j-1]+1,j-vis[M[i][j]]);
            vis[M[i][j]]=j;
        }
    }
    for(int j=1;j<=m;j++){
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++){
            uu[i][j]=min(uu[i-1][j]+1,i-vis[M[i][j]]);
            vis[M[i][j]]=i;
        }
    }
    for(int j=1;j<=m;j++){//遍历每一列
        //每一列的遍历中公用与维护sta
        memset(sta,0,sizeof(sta));
        for(int i=1;i<=n;i++){
            for(int k=0;k<l[i][j];k++){
                int p=j-k;
                sta[k]=min(sta[k]+1,uu[i][p]);//得到这一个位置的往上走的上限
                if(k)sta[k]=min(sta[k],sta[k-1]);//和之前的sta比较
                ans+=(long long)sta[k];
            }
            for(int k=l[i][j];k<=54;k++)sta[k]=0;//这部分清0限制下个i的sta[k]
        }
    }
}


int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%s",M[i]+1);
    init();
    cout<<ans<<endl;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值