题目大意:给定一个n∗n的矩阵,初始都为0,选择一个1到n∗n的排列,然后按照这个排列的顺序,每次选择这个矩阵的一个非空子矩形,然后涂上当前数字。
现在给定最终的矩阵,求哪些数字可能是排列的第一位。
写输入法写成傻逼回来换换脑子……
开一个新的n∗n的矩阵cnt,初始全0
对于每个数字统计出出现的最上u最下d最左l最右r,然后就能框出一个矩形,把cnt[u,d][l,r]加上1,表示有一个矩形在这个位置至少涂了一次
如果一个格子的cnt>1,说明有超过一个矩形在这里涂了数字,那么这个格子最终的数字一定不能最先涂
剩下的就是能最先涂的数字。
特殊情况:n≠1且最终矩阵里除了0外只有一种数字,那么这个数字肯定不能先涂,要从答案中扣除。
时间复杂度O(n2)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 1010
using namespace std;
int n,cnt,ans;
int a[M][M],b[M][M];
int u[M*M],d[M*M],l[M*M],r[M*M];
bool killed[M*M];
int main()
{
cin>>n;
memset(u,0x3f,sizeof u);
memset(l,0x3f,sizeof l);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
scanf("%d",&a[i][j]);
if(a[i][j])
{
if(u[a[i][j]]==0x3f3f3f3f)
++cnt;
u[a[i][j]]=min(u[a[i][j]],i);
d[a[i][j]]=max(d[a[i][j]],i);
l[a[i][j]]=min(l[a[i][j]],j);
r[a[i][j]]=max(r[a[i][j]],j);
}
}
for(int i=1;i<=n*n;i++)
if(u[i]!=0x3f3f3f3f)
{
b[u[i]][l[i]]++;
b[d[i]+1][l[i]]--;
b[u[i]][r[i]+1]--;
b[d[i]+1][r[i]+1]++;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(a[i][j] && b[i][j]>1)
killed[a[i][j]]=true;
for(int i=1;i<=n*n;i++)
if(!killed[i])
++ans;
if(cnt==1 && n!=1)
--ans;
cout<<ans<<endl;
return 0;
}