百题计划-1 codeforces1181C Flag 暴力模拟

https://codeforces.com/contest/1181/problem/C

题意:给一个n*m的格子(n,m<=1000),每个格子有个颜色,求可以条纹子矩阵的数量。

条纹矩阵就是如图

 

 解法:

先预处理出每个点向下和它同字符能扩展到的位置down[i][j],然后暴力枚举顶点,检查即可。复杂度o(n*m)。

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn=1000100;
const int INF=(1<<29);

int n,m;
char s[1100][1100];
int down[1100][1100];

void init_down(){
    for(int j=1;j<=m;j++){
        int l=1,r=1;
        for(;l<=n;){
            while(r+1<=n && s[r+1][j]==s[l][j]) r++;
            for(int i=l;i<=r;i++) down[i][j]=r-i+1;
            l=r+1;r=l;
        }
    }
}

bool check(int i,int j,int cnt,int k){
    if(s[i][j]!=s[i][k] || s[i+cnt][j]!=s[i+cnt][k] || s[i+2*cnt][j]!=s[i+2*cnt][k]) return 0;
    return down[i][k]==cnt && down[i+cnt][k]==cnt && down[i+2*cnt][k]>=cnt;
}

void solve(){
    for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) down[i][j]=0;
    init_down();
    ll res=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;){
            int cnt=down[i][j];
            if(i+3*cnt-1>n||!check(i,j,cnt,j)){
                j++;continue;
            }
            int k=j;
            while(k+1<=m&&check(i,j,cnt,k+1)) k++;
            int w=k-j+1;
            res+=1LL*w*(w+1)/2;
            j=k+1;
        }
    }
    cout<<res<<endl;
}

int main(){
    // freopen("in.txt","r",stdin);
    while(cin>>n>>m) solve();
    return 0;
}
View Code

 

posted on 2020-08-13 18:29  KEZ  阅读(77)  评论(0)    收藏  举报

导航