题意
给你一个的矩阵,有
个颜色在一个矩阵中涂色(每种颜色必须要涂),求出第一个涂色的颜色可能有多少种
做法:二维差分
思路
- 首先把明面上留下的颜色给记录下来,并且存可能涂色的最小矩阵的四个顶点坐标
- 然后模拟涂色,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;
}

京公网安备 11010502036488号