题目链接:https://www.luogu.com.cn/problem/P7410
分析
将矩阵预处理,小于100赋值-1,等于100赋值0,大于100赋值1。
用一个数组算出从右到左每一行的非-1的最长的“延伸”距离。
比如样例:
处理成:
0 1 0
3 2 1
0 2 1
然后利用这个(的一些类似前缀和的处理)就可以求出任意以 ( i , j ) (i,j) (i,j)为左上角的矩阵个数
然后抠掉所有的100,再做一次同样的东西(预处理也要重新做)。两次相减就可以。
上代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
int n,a[501][501],f[501][501];
ll s1,s2;
void pre()
{
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++)
{
for(int j=n;j>=1;j--)
{
if(a[i][j]!=-1) f[i][j]=f[i][j+1]+1;
}
}
}
int matrix(int x,int y)//以(x,y)为左上角的矩阵个数
{
ll sum=0;
int mn=819;
for(int i=x;i<=n;i++)
{
if(a[i][y]==-1) break;
mn=min(mn,f[i][y]);//实时最小延伸数
sum+=mn;
}
cout<<sum<<' ';
return sum;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
int x;
scanf("%d",&x);
if(x>100) a[i][j]=1;
else if(x<100) a[i][j]=-1;
else a[i][j]=0;
}
}
pre();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cout<<f[i][j]<<' ';
}
cout<<endl;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
s1+=matrix(i,j);
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(a[i][j]==0) a[i][j]=-1;
}
}
pre();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
s2+=matrix(i,j);
}
}
cout<<s1-s2;
return 0;
}