ZOJ1610 Count the Colors

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1610

貌似线段树的区间染色是一个非常常见的题型吧,但是不得不说。。我昨天刚刚碰到,而且统计每一种颜色占了多少个不连续区间的时候着实不会写,表示前面把树建出来和更新的步骤都是纯我自己写的,就是查找颜色个数那一步。。。不得不参考了,最后弄明白了。

如果一个区间没有染色或者有多种颜色,都会有标记,如果有了标记,就可以不用考虑这个结点了,直接找它的两个儿子就行了。如果证实某一个区间被染过色而且里面仅仅有一个颜色,那么就可以与其相邻子树比较然后再更新结果值(要求的是每种颜色占的不连续区间数量,相邻子树代表的是连续区间,所以就得这么比较),然后直接退出这个状态(都说了里面只有一个颜色,就没有找它儿子的必要了)。。

#include <cstdio>
#include <cstring>
#define lson l, m, rt << 1
#define rson m, r, rt << 1 | 1
const int maxn = 8111;
int col[maxn << 2], tmp, num[maxn];
void PushDown(int rt){
    if (col[rt] >= 0){
        col[rt << 1] = col[rt];
        col[rt << 1 | 1] = col[rt];
        col[rt] = -2;
    }
}
void build(int l, int r, int rt){
    col[rt] = -1;
    if (l == r - 1) return;
    int m = (l + r) >> 1;
    build(lson);
    build(rson);
}
void update(int ll, int rr, int c, int l, int r, int rt){
    if (col[rt] == c) return;
    if (ll <= l && rr >= r){
        col[rt] = c;
        return;
    }
    PushDown(rt);
    int m = (l + r) >> 1;
    if (ll < m) update(ll, rr, c, lson);
    if (rr > m) update(ll, rr, c, rson);
}
void query(int l, int r, int rt){
    if (col[rt] != -1 && col[rt] != -2){
        if (col[rt] != tmp) num[col[rt]] += 1;
        tmp = col[rt];
        return;
    }
    if (l == r - 1){
        tmp = -1; return;
    }
    int m = (l + r) >> 1;
    query(lson); query(rson);
}
int main(){
    //freopen("in.txt", "r", stdin);
    int n;
    while(~scanf("%d", &n)){
        build(0, 8000, 1);
        memset(num, 0, sizeof(num));
        while(n--){
            int x, y, z;
            scanf("%d%d%d", &x, &y, &z);
            update(x, y, z, 0, 8000, 1);
        }
        tmp = -1;
        query(0, 8000, 1);
        for (int i = 0; i <= 8000; i++)
            if (num[i]) printf("%d %d\n", i, num[i]);
        printf("\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值