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 namespace std;
using ll = long long;
#define rep(i,a,b) for(ll i=a;i<=b;i++)
#define per(i,a,b) for(ll i=b;i>=a;i--)
const ll inf = 1e18;
const ll N = 200005;
ll H, W, M, T[N], A[N], X[N], C[N], visX[N], visY[N];
//////////////////////////////////////////////
int __ginit__ = []() {
cin.tie(0)->sync_with_stdio(0);
return 0;
}();
void solve() {
cin >> H >> W >> M;
rep(i,1,M) cin >> T[i] >> A[i] >> X[i];
ll nrow = H, ncol = W;
per(i,1,M) {
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;
}
}
}
ll cnt = 0, sum = 0;
rep(i,1,N-1) if (C[i]) {
cnt += 1;
sum += C[i];
}
ll unvis = H * W - sum - C[0];
C[0] += unvis;
if (C[0]) cnt += 1;
cout << cnt << "\n";
rep(i,0,N-1) if (C[i]) {
cout << i << " " << C[i] << "\n";
}
}
int main() {
ll t = 1;
while (t--) solve();
return 0;
}