ZOJ 1610 Count the Colors (线段树成段更新)

题意 : 给出 n 个染色操作,问你到最后区间上能看见的各个颜色所拥有的区间块有多少个

 

分析 : 使用线段树成段更新然后再暴力查询总区间的颜色信息即可,这里需要注意的是给区间染色,而不是给点染色,所以对于区间(L, R)我们只要让左端点+1即可按照正常的线段树操作来做。

 

#include<bits/stdc++.h>
#define lson l,   m, rt<<1
#define rson m+1, r, rt<<1|1
using namespace std;
const int maxn = 8000 + 5;
const int INF = 0x3f3f3f3f;
struct Query{ int L, R, val; };
int col[maxn<<2], cnt[maxn], Rmax, ColorMax;
Query Q[maxn];

inline void PutDown(int rt)
{
    if(col[rt] >= 0){
        col[rt<<1] = col[rt<<1|1] = col[rt];
        col[rt] = -1;
    }
}

inline void update(int L, int R, int val, int l, int r, int rt)
{
    if(L <= l && r <= R){
        col[rt] = val;
        return ;
    }
    PutDown(rt);
    int m = (l + r) / 2;
    if(L <= m) update(L, R, val, lson);
    if(R >  m) update(L, R, val, rson);
}

int query(int pos, int l, int r, int rt)
{
    if(l == r) return col[rt];
    PutDown(rt);
    int m = (l + r) / 2;
    int ret;
    if(pos <= m) ret = query(pos, lson);
    if(pos >  m) ret = query(pos, rson);
    return ret;
}

int main(void)
{
    int paint;
    while(~scanf("%d", &paint)){

        Rmax = ColorMax = -INF;

        for(int i=1; i<=paint; i++){
            scanf("%d %d %d", &Q[i].L, &Q[i].R, &Q[i].val);
            Q[i].L++;
            Rmax = max(Rmax, Q[i].R);///记录区间右端可以多大
            ColorMax = max(ColorMax, Q[i].val);///记录颜色的最大值
        }
        
        memset(col, -1, sizeof(col));
        for(int i=1; i<=paint; i++){
            if(Q[i].L-1 < Q[i].R)///说明给出的是一个点,没有覆盖掉哪一段,不用更新
                update(Q[i].L, Q[i].R, Q[i].val, 1, Rmax, 1);
        }

        memset(cnt, 0, sizeof(cnt));
        int last = -1;
        for(int i=1; i<=Rmax; i++){///查询区间内每个点的信息,用cnt[]数组来记录拥有的这些颜色占的段数
            int color = query(i, 1, Rmax, 1);
            if(color == -1) {last = -1; continue;}///注意如果没有被染色,last要赋值成-1,不能直接continue
            if(color != last){
                cnt[color]++;
            }
            last = color;
        }

        for(int i=0; i<=ColorMax; i++){
            if(cnt[i]>0){
                printf("%d %d\n", i, cnt[i]);
            }
        }
        puts("");
    }
    return 0;
}
View Code

 

瞎 : query操作的时候由于有lazy tag所以需要PutDown,此题虽然不难但是如果独立写一个线段树并且AC估计能够发现自身的一些问题,注意实现细节....

转载于:https://www.cnblogs.com/LiHior/p/7411546.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值