[BZOJ4776] [Usaco2017 Open]Modern Art(差分 + 思维?)
可以预处理出每种颜色的上下左右的位置,这样就框出来了一个个矩形,代表每种颜色分别涂了哪里。
然后用二维的差分。
就可以求出来每个位置至少涂了几次,如果 > 1 的话,就肯定不是先涂的,
如果是1的话,并且不是只有一种颜色,那么也有可能是先涂的,
如果只有一种颜色,并且 n != 1,那么一定不是先涂的,如果 n == 1,也就只有一种颜色了,那么它就是先涂的
#include <cstdio>
#include <cstring>
#include <iostream>
#define N 1011
using namespace std;
int n, cnt, ans;
int a[N][N], b[N][N], u[N * N], d[N * N], l[N * N], r[N * N];
bool vis[N * N];
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
return x * f;
}
int main()
{
int i, j, x;
n = read();
memset(u, 127, sizeof(u));
memset(l, 127, sizeof(l));
for(i = 1; i <= n; i++)
for(j = 1; j <= n; j++)
{
a[i][j] = read();
if(a[i][j])
{
if(u[a[i][j]] >= 1e9) ++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(i = 1; i <= n * n; i++)
if(u[i] <= 1e9)
{
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(i = 1; i <= n; i++)
for(j = 1; j <= n; j++)
{
b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1];
if(a[i][j] && b[i][j] > 1)
vis[a[i][j]] = 1;
}
for(i = 1; i <= n * n; i++)
if(!vis[i])
ans++;
if(cnt == 1 && n != 1) ans--;
printf("%d\n", ans);
return 0;
}

浙公网安备 33010602011771号