最新文章

这里会显示最新的几篇文章摘要。

染色(二分)

问题 C: 染色center>

题目描述

在古希腊的神话中,有一位掌管刷墙的神。他面前有一面大小为n*m的白墙,他有k+1种颜料(白色为 0 号,其他颜色分别为 1 到 k)。神将进行q次粉刷操作,每次使用宽度为 1 单位的刷子,染色后覆盖一整行或者一整列。现在给出他的所有操作,你能告诉他,除白色外,每种颜色的最后覆盖面积吗?

输入

第一行包含四个整数n,m,k,q。

接下来q行描述q次粉刷操作。

每行包含三个正整数opt,u,c:

  • 当opt = 0时,表示将第u列刷成颜色c。
  • 当opt=1时,表示将第u行刷成颜色c。

输出

输出一行包含k个整数,分别表示每种颜色的最终覆盖面积。

样例输入

5 5 2 2
1 1 1
0 1 2

样例输出

4 5

提示

对于30%的数据,满足n≤100,0≤q≤100
对于50%的数据,满足n≤5000,0≤q≤5000
对于100%的数据,满足n,m≤10^5, q≤10^5, 0≤k≤10^5

分析

题意是统计经过q次粉刷过后墙壁每个颜色的个数,怎么统计最后的颜色,遍历的话会超时,因此考虑二分查找哪些区块的粉刷时间比较早,比较早的会被当前的颜色覆盖掉。
分别记录行和列的颜色和粉刷次序,对粉刷次序进行排序,统计第i列的颜色的时候,第i列里每一个行的粉刷次序比较早的就会被记为一个。

代码

struct cow {
    int id = 0;
    int val;

    bool operator < (const cow& a) const {
        return id < a.id;
    }

};
cow c[100005],r[100005];  //行和列
int idx;                  //记录次序
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    //
    // freopen("E:/Code/C++/untitled1/input.txt","r",stdin);
    // freopen("output.txt","w",stdout);

    int n, m, k, q;
    cin >> n >> m >> k >> q;
    while (q--) {
        int o, u, p;
        cin >> o >> u >> p;
        if (o==1) {
            c[u].val = p;   //列粉刷
            c[u].id = ++idx;
        }
        else {
            r[u].val = p;
            r[u].id = ++idx;
        }
    }
    sort(c+1,c+1+n);      //对行列排序
    sort(r+1,r+1+m);

    vector<int> color(k+1);

    for (int i = 1;i <= n;++i) {   //对统计行颜色
        if (r[i].id == 0) continue;
        auto it = lower_bound(c+1,c+m+1,r[i]) - (c+1);  //比该行颜色粉刷早的个数
        color[r[i].val] += it;//de(it);
    }
    for (int i = 1;i <= m;++i) {  //对列统计
        if (c[i].id == 0) continue;
        auto it = lower_bound(r+1,r+1+m,c[i]) - (r+1);
        color[c[i].val] += it;
    }

    for (int i = 1;i <= k;++i) cout << color[i] << ' ';
}

posted @ 2025-03-08 11:11  bakul  阅读(28)  评论(0)    收藏  举报