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;
}

posted @ 2024-03-24 15:51  chenfy27  阅读(13)  评论(0编辑  收藏  举报