abc346E 网格染色
有个H行W列的网格,初始时所有格子的颜色为0,现有m组操作,格式为: T[i] A[i] X[i],当T[i]=1时,表示将第A[i]行都涂上第X[i]种颜色;当T[i]=2时,表示将第A[i]列都涂上第X[i]种颜色。后涂的颜色会覆盖先涂的颜色。
问全部操作完后,共有多少种颜色,以及每种颜色的数目。
1<=H,W,M<=2e5; T[i]=1时1<=A[i]<=H; T[i]=2时1<=A[i]<=W; 0<=X[i]<=2e5
分析:由于后面上的色会覆盖前面上的色,考虑逆序处理。
用nrow和ncol维护还没有上色的行数和列数,并用visX和visY维护当前行或者列是否已上过色。
由于初始时颜色为0,并且上色操作也可能用颜色0,无法区分,因此颜色0要单独考虑。
#include <bits/stdc++.h>
using i64 = long long;
const i64 N = 200005;
i64 H, W, M, T[N], A[N], X[N], C[N], visX[N], visY[N];
void solve() {
std::cin >> H >> W >> M;
for (int i = 1; i <= M; i++) {
std::cin >> T[i] >> A[i] >> X[i];
}
i64 nrow = H, ncol = W;
for (int i = M; i >= 1; i--) {
if (T[i] == 1) {
if (!visX[A[i]]) {
visX[A[i]] = 1;
C[X[i]] += ncol;
nrow -= 1;
}
} else {
if (!visY[A[i]]) {
visY[A[i]] = 1;
C[X[i]] += nrow;
ncol -= 1;
}
}
}
i64 cnt = 0, sum = 0;
for (int i = 1; i <= N - 1; i++) {
if (C[i]) {
cnt += 1;
sum += C[i];
}
}
i64 unvis = H * W - sum - C[0];
C[0] += unvis;
if (C[0]) {
cnt += 1;
}
std::cout << cnt << "\n";
for (int i = 0; i <= N - 1; i++) {
if (C[i]) {
std::cout << i << " " << C[i] << "\n";
}
}
}
int main() {
std::cin.tie(0)->sync_with_stdio(0);
int t = 1;
while (t--) solve();
return 0;
}
浙公网安备 33010602011771号