• 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
    ", i, cnt[i]);
                }
            }
            puts("");
        }
        return 0;
    }
    View Code

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

  • 相关阅读:
    LInq 与lambda表达式
    Java内存模型-jsr133规范介绍(转)
    Java多线程之Lock的使用(转)
    有一个很大的整数list,需要求这个list中所有整数的和,写一个可以充分利用多核CPU的代码,来计算结果(转)
    CountDownLatch
    CyclicBarrier
    java设计模式演示样例
    2012毕业找工作记录点滴
    Objective-C语法之代码块(block)的使用
    权限表设计之代码解析
  • 原文地址:https://www.cnblogs.com/qwertiLH/p/7411546.html
Copyright © 2020-2023  润新知