Count the Colors

题目

在[0,8000]区间进行N次区间染色,后涂的色可以覆盖之前涂的色,问N次染色之后,能看见的颜***间数量各是多少?

分析

其实这题区间覆盖这部分很好做,不需要离散化,因为只有8000长度的区间。我们要注意的是,需要将区间改成左开右闭的形式,比如给[0,2],[2,4]区间染色,要变成给[1,2],[3,4]染色。这样才不会有冲突。
然后N次染色之后,将有色的区间进行统计一下,能合并的就合并。然后输出就可以了

AC 代码

#include <iostream>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <map>
#include <cstring>
#define X first
#define Y second
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn  = 8e3+10;
int M;
struct node{
    int l,r,tag;
}tr[4*maxn];
vector<pii> h[maxn];
map<int,int> mp;
void pushup(int u){
    node &fa = tr[u],&L = tr[u*2],&R = tr[u*2+1];
    if(L.tag == R.tag){
        fa.tag = L.tag;
    }else{
        fa.tag = -1;
    }
}
void pushdown(int u){
    node &fa = tr[u],&L = tr[u*2],&R = tr[u*2+1];
    if(fa.tag > 0){
        L.tag = fa.tag;
        R.tag = fa.tag;
    }
}
void build(int u,int l,int r){
    tr[u] = {l,r};
    if(l != r){
        int mid = l+r>>1;
        build(u*2,l,mid);
        build(u*2+1,mid+1,r);
    }
}
void modify(int u,int l,int r,int tag){
    if(tr[u].l>=l && tr[u].r<=r){
        tr[u].tag = tag;
    }else{
        pushdown(u);
        int mid = (tr[u].l+tr[u].r)>>1;
        if(l<=mid) modify(u*2,l,r,tag);
        if(r>mid) modify(u*2+1,l,r,tag);
        pushup(u);
    }
}
void query(int u,int l,int r){
    if(tr[u].tag == 0) return ;
    if(tr[u].tag>0){
        h[tr[u].tag].emplace_back(tr[u].l,tr[u].r);
        //cout<<tr[u].l<<" "<<tr[u].r<<" "<<tr[u].tag<<endl;
    }else{
        pushdown(u);
        query(u*2,l,r);
        query(u*2+1,l,r);
        pushup(u);
    }
}

void fun(){
    for(int i  = 1;i<=8000;i++) {
        sort(h[i].begin(),h[i].end());
        int l = -1,r = -1,cnt = -1;
        for(auto p:h[i]){ //合并区间,并统计
            int x = p.X,y = p.Y;
            if(x>r+1){
                cnt ++;
                l = x;
                r = y;
            }else{
                r = y;
            }
        }
        if(h[i].size()) mp[i] = cnt+1;
    }
    for(auto p:mp){
        printf("%d %d\n",p.X-1,p.Y);//前面+1了,现在-1
    }
    puts("");
}
int main(){
    while(~scanf("%d",&M)){
        memset(tr,0,sizeof tr);
        mp.clear();
        for(int i = 1;i<=8000;i++) h[i].clear();
        build(1,1,8000);
        int a,b,c;
        while(M--){
            scanf("%d%d%d",&a,&b,&c);
            modify(1,a+1,b,c+1);//+1是因为我想从1开始
        }
        query(1,1,8000);
        fun();
    }
    return 0;
}