chenfy27的刷题记录

导航

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

posted on 2024-03-24 15:51  chenfy27  阅读(39)  评论(0)    收藏  举报