zoukankan      html  css  js  c++  java
  • zoj 1610 Count the Colors

    这里主要复习下线段树点的意义。这里的染色区域L,和R,是指将这样一个线段[L,R]染色,而非点染色。那么,我们可以人为地改变线段树中每个点的意义:从树原本的一个叶子表示一个点,改成表示一条长度为1的线段。比如[1,2]这个线段,用2来表示即可,那么染色[u,v],相当于染色[u+1,v]。问题来了:为什么不用1来表示[1,2]呢?

    因为:用末端来表示线段,相当于用(a,b]表示这条线段,即后端准确,前面的线段即使和a重合,也不影响(a,b]。

    假设是用首端来表示线段,相当于用[a,b)表示,即前端准确,假设前面的线段和a重合,比如染色b->c为A色,再染a->b为B色,那么b被B占领,实际上的b->(b+1)这段颜色被消灭了(这不应该)。

    #include <stdio.h>
    #include <memory.h>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    
    #define ll long long
    #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
    #define DOR(i,a,b) for(int i=(a);i>=(b);--i)
    
    const int maxN=8e3+5,inf=0x3f3f3f3f;
    int N, M, K, T;
    // g[rt]: -1:不必更新
    int cr[maxN<<4], g[maxN<<4];
    int ans[maxN];
    
    #define lson l,m,rt*2
    #define rson m+1,r,rt*2+1
    
    void push_down(int rt) {
        if (g[rt] == -1) return;
        int lch = rt * 2, rch = lch + 1;
        g[lch] = g[rch] = g[rt];
        cr[lch] = cr[rch] = g[rt];
        g[rt] = -1;
    }
    void update(int L, int R, int C, int l, int r, int rt) {
        if (L <= l && r <= R) {
            g[rt] = C;
            cr[rt] = C;
            return;
        }
        push_down(rt);
        int m = (l + r) / 2;
        if (L <= m) update(L, R, C, lson);
        if (R > m) update(L, R, C, rson);
    }
    int pre, first;
    void query(int l, int r, int rt) {
        if (l == r) {
            if (first) {
                first = 0;
            }
            if (cr[rt] != pre && cr[rt] != -1)
                ans[cr[rt]]++;
            pre = cr[rt];
            return;
        }
        push_down(rt);
        int m = (l + r) / 2;
        query(lson);
        query(rson);
    }
    
    int main () {
    #ifndef ONLINE_JUDGE
        freopen("data.in", "r", stdin);
    #endif
        N = 8000 + 1;
        // N = 3;
        while (~scanf("%d", &M)) {
            // build tree
            memset(g, -1, sizeof g);
            memset(cr, -1, sizeof cr);
            memset(ans, 0, sizeof ans);
    
            int u, v, w;
            FOR(i, 1, M) {
                scanf("%d%d%d", &u, &v, &w);
                update(u + 1, v, w, 0, N, 1);
            }
            first = 1;
            query(0, N, 1);
            FOR(i, 0, N)
                if (ans[i])
                    printf("%d %d
    ", i, ans[i]);
            puts("");
        }
        return 0;
    }
  • 相关阅读:
    [原创]RTX使用printf输出后进入hardfault中断的处理方法
    [原创]单片机 HexToStr and HexToBcd BcdToStr
    [原创]单片机-HexToStr or HexToAsc
    再看 AspriseOCR
    [源创] STM32F103ZET6 基于XMODEM 通讯的 BOOTLOADER案列IAP
    单片机串口——如何判定接收一帧数据的完成
    [原创] 关于步科eview人机界面HMI的使用
    [原创] STM32 定时器TIMx 编码器应用 函数 TIM_EncoderInterfaceConfig 分析
    单片机的 HexToStr HexToBcd BcdToStr 几个转换函数
    [转载] 全局键盘钩子(WH_KEYBOARD)
  • 原文地址:https://www.cnblogs.com/Rosebud/p/9627003.html
Copyright © 2011-2022 走看看