题意
给你一个的矩阵,有个颜色在一个矩阵中涂色(每种颜色必须要涂),求出第一个涂色的颜色可能有多少种
做法:二维差分
思路
- 首先把明面上留下的颜色给记录下来,并且存可能涂色的最小矩阵的四个顶点坐标
- 然后模拟涂色,w[i][j]表示这个位置最小被涂色的次数,这里可以采用二维差分来优化
- 如果这个位置被多次(大于1次)涂色,那么明面上留下的颜色必不可能是第一次涂色,减去即可
- 注意n=1和明面上只留下一种颜色的情况时进行特判即可
代码
// Problem: Modern Art // Contest: NowCoder // URL: https://ac.nowcoder.com/acm/problem/24093 // Memory Limit: 65536 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org) #include <bits/stdc++.h> using namespace std; #define pb push_back #define mp(aa,bb) make_pair(aa,bb) #define _for(i,b) for(int i=(0);i<(b);i++) #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define per(i,b,a) for(int i=(b);i>=(a);i--) #define mst(abc,bca) memset(abc,bca,sizeof abc) #define X first #define Y second #define lowbit(a) (a&(-a)) #define debug(a) cout<<#a<<":"<<a<<"\n" typedef long long ll; typedef pair<int,int> pii; typedef unsigned long long ull; typedef long double ld; const int N=1005; const int INF=0x3f3f3f3f; const int mod=1e9+7; const double eps=1e-6; const double PI=acos(-1.0); int a[N][N],b[N][N],w[N][N]; int l[N*N],r[N*N],up[N*N],down[N*N]; set<int> s,ss; void solve(){ mst(l,INF);mst(up,INF); int n;cin>>n; rep(i,1,n) rep(j,1,n){ cin>>a[i][j]; if(!a[i][j]) continue; s.insert(a[i][j]); l[a[i][j]]=min(l[a[i][j]],j); r[a[i][j]]=max(r[a[i][j]],j); up[a[i][j]]=min(up[a[i][j]],i); down[a[i][j]]=max(down[a[i][j]],i); } if(n==1){ cout<<1<<"\n"; return; } if(s.size()==1){ cout<<n*n-1<<"\n"; return; } for(int x:s){ int x1=up[x],y1=l[x],x2=down[x],y2=r[x]; b[x1][y1]++; b[x2+1][y1]--; b[x1][y2+1]--; b[x2+1][y2+1]++; } s.clear(); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ w[i][j]=w[i-1][j]+w[i][j-1]-w[i-1][j-1]+b[i][j]; // debug(w[i][j]); if(w[i][j]>1) s.insert(a[i][j]); } } // for(int x:s) debug(x); cout<<n*n-s.size()<<"\n"; } int main(){ ios::sync_with_stdio(0);cin.tie(0); // int t;cin>>t;while(t--) solve(); return 0; }