CodeForces - 253D(前缀和+有技巧的暴力)

原题链接

  1. 题目大意
    对于一个字符矩阵,找其中的子块,要求有两个其一子块中包含字符a的个数不超过k,其二子块的四个角的字符相同。

  2. 思路
    首先保证字符a的个数,可以用求前缀和预处理每个子块中a的个数;其次暴力枚举,不过暴力枚举要上下左右四个变量,四重循环会超时,这时候可以用两个变量枚举上下,再用一个变量枚举左,此时判断当前列对于上行和下行来说字符是否相同,再用一个值控制右,但对于左右来说相同的上下行,只暴力一遍。最后就是三重循环的复杂度。
    处理方法:用一个数组储存相同字符出现的次数,同时要注意对于每次相同的字符要减去一,控制右边的数值从一开始遍历,会经过控制左边的变量,而最后求的是满足条件的子块,所以要减去一。具体看代码。

  3. 代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+10;
char a[500][500];
int num[500][500];
int main()
{
    ///freopen("input.txt", "r", stdin);
    ///freopen("output.txt", "w", stdout);
    int n,m,kk;
    scanf("%d%d%d",&n,&m,&kk);
    for(int i=1; i<=n; i++)
        scanf("%s",a[i]+1);
    memset(num,0,sizeof(num));
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m; j++)
        {
            num[i][j]=num[i-1][j]+num[i][j-1]-num[i-1][j-1];//预处理a的个数
            if(a[i][j]=='a') num[i][j]++;
        }
    ll ans=0;
    int q[300];
    for(int i=1; i<=n; i++)//上行
    {
        for(int j=i+1; j<=n; j++)//下行
        {
            int p=1;//右
            memset(q,0,sizeof(q));
            for(int k=1; k<=m; k++)//左
            {
                if(a[i][k]!=a[j][k]) continue;
                while(p<=m&&num[j][p]-num[i-1][p]-num[j][k-1]+num[i-1][k-1]<=kk)
                {
                    if(a[i][p]==a[j][p]) q[a[i][p]]++;//如果满足条件对应字符加一
                    p++;
                }
                q[a[i][k]]--;//放在while前后都可以,减去的是本身出现的这一次
                if(q[a[i][k]]>0) ans=ans+q[a[i][k]];
            }
        }
    }
    printf("%I64d\n",ans);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值