https://codeforces.com/contest/1393/problem/D
先每一列从上往下扫再从下往上扫,得到每个位置向下最远多少,向上最远多少,然后取min得到他在竖直方向最大多少
然后每一行从左往右扫再从右往左扫,由于他的形状特性,那么当前位置可最多拓展的图形个数就是min(l[i][j-1]+1,h[i][j],r[i][j+1]+1)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxl=2e3+10;
int n,m;ll ans;
int a[maxl][maxl];
int u[maxl][maxl],d[maxl][maxl],h[maxl][maxl];
int l[maxl][maxl],r[maxl][maxl];
char s[maxl][maxl];
inline void prework()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%s",s[i]+1);
for(int j=1;j<=m;j++)
{
for(int i=1;i<=n;i++)
if(s[i][j]==s[i-1][j])
u[i][j]=u[i-1][j]+1;
else
u[i][j]=1;
for(int i=n;i>=1;i--)
if(s[i][j]==s[i+1][j])
d[i][j]=d[i+1][j]+1;
else
d[i][j]=1;
for(int i=1;i<=n;i++)
h[i][j]=min(u[i][j],d[i][j]);
}
}
inline void mainwork()
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
if(s[i][j]==s[i][j-1])
l[i][j]=min(l[i][j-1]+1,h[i][j]);
else
l[i][j]=1;
for(int j=m;j>=1;j--)
if(s[i][j]==s[i][j+1])
r[i][j]=min(r[i][j+1]+1,h[i][j]);
else
r[i][j]=1;
for(int j=1;j<=m;j++)
ans+=min(l[i][j],r[i][j]);
}
}
inline void print()
{
printf("%lld",ans);
}
int main()
{
prework();
mainwork();
print();
return 0;
}