https://www.51nod.com/Challenge/Problem.html#!#problemId=1580
top[i][j]=1代表在第j列 从0到i行都没有障碍 bot lef rgt同理
管道就四种情况 两端点在同一边缘 在相邻边缘 在相对边缘 分情况处理即可 利用上面四个数组的前缀和可以n^2
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e3+10;
int top[maxn][maxn],bot[maxn][maxn],lef[maxn][maxn],rgt[maxn][maxn],sumtop[maxn][maxn],sumbot[maxn][maxn];
int n,m;
char ch[maxn][maxn],tmp[maxn][maxn];
ll solveI()
{
ll res;
int i,j;
for(j=0;j<m;j++){
for(i=0;i<n;i++){
if(i==0) top[i][j]=(ch[i][j]=='.');
else top[i][j]=(top[i-1][j]&&ch[i][j]=='.');
}
for(i=n-1;i>=0;i--){
if(i==n-1) bot[i][j]=(ch[i][j]=='.');
else bot[i][j]=(bot[i+1][j]&&ch[i][j]=='.');
}
}
for(i=0;i<n;i++){
for(j=0;j<m;j++){
if(j==0) lef[i][j]=(ch[i][j]=='.');
else lef[i][j]=(lef[i][j-1]&&ch[i][j]=='.');
}
for(j=m-1;j>=0;j--){
if(j==m-1) rgt[i][j]=(ch[i][j]=='.');
else rgt[i][j]=(rgt[i][j+1]&&ch[i][j]=='.');
}
}
res=0;
for(i=1;i<n-1;i++){
for(j=1;j<m-1;j++){
if(top[i][j]&&lef[i][j]) res++;
if(top[i][j]&&rgt[i][j]) res++;
if(bot[i][j]&&lef[i][j]) res++;
if(bot[i][j]&&rgt[i][j]) res++;
}
}
return res;
}
void flip()
{
int i,j;
for(i=0;i<n;i++){
for(j=0;j<m;j++){
tmp[j][i]=ch[i][j];
}
}
swap(n,m);
for(i=0;i<n;i++){
for(j=0;j<m;j++){
ch[i][j]=tmp[i][j];
}
}
}
ll solveII()
{
ll res;
int i,j,k,p;
for(j=0;j<m;j++){
for(i=0;i<n;i++){
if(i==0) top[i][j]=(ch[i][j]=='.');
else top[i][j]=(top[i-1][j]&&ch[i][j]=='.');
}
for(i=n-1;i>=0;i--){
if(i==n-1) bot[i][j]=(ch[i][j]=='.');
else bot[i][j]=(bot[i+1][j]&&ch[i][j]=='.');
}
}
res=0;
for(j=1;j<m-1;j++) if(top[n-1][j]) res++;
for(i=0;i<n;i++){
for(j=0;j<m;j++){
if(j>0){
sumtop[i][j]=sumtop[i][j-1]+top[i][j];
sumbot[i][j]=sumbot[i][j-1]+bot[i][j];
}
else{
sumtop[i][j]=top[i][j];
sumbot[i][j]=bot[i][j];
}
}
}
for(i=1;i<n-1;i++){
p=0;
for(j=1;j<m-1;j++){
if(ch[i][j]=='#'){
for(k=p+1;k<=j-1;k++){
if(top[i][k]&&k-2>=p+1) res+=(ll)(sumtop[i][k-2]-sumtop[i][p]);
if(bot[i][k]&&k-2>=p+1) res+=(ll)(sumbot[i][k-2]-sumbot[i][p]);
if(top[i][k]) res+=((ll)(sumbot[i][k-1]-sumbot[i][p])+(ll)(sumbot[i][j-1]-sumbot[i][k]));
}
p=j;
}
}
for(k=p+1;k<=j-1;k++){
if(top[i][k]&&k-2>=p+1) res+=(ll)(sumtop[i][k-2]-sumtop[i][p]);
if(bot[i][k]&&k-2>=p+1) res+=(ll)(sumbot[i][k-2]-sumbot[i][p]);
if(top[i][k]) res+=((ll)(sumbot[i][k-1]-sumbot[i][p])+(ll)(sumbot[i][j-1]-sumbot[i][k]));
}
}
return res;
}
int main()
{
ll ans;
int i;
scanf("%d%d",&n,&m);
for(i=0;i<n;i++) scanf("%s",ch[i]);
ans=solveI();
ans+=solveII();
flip();
ans+=solveII();
printf("%lld\n",ans);
return 0;
}