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;
    }
  • 相关阅读:
    poj 2763 Housewife Wind
    hdu 3966 Aragorn's Story
    poj 1655 Balancing Act 求树的重心
    有上下界的网络流问题
    URAL 1277 Cops and Thieves 最小割 无向图点带权点连通度
    ZOJ 2532 Internship 网络流求关键边
    ZOJ 2760 How Many Shortest Path 最大流+floyd求最短路
    SGU 438 The Glorious Karlutka River =) 拆点+动态流+最大流
    怎么样仿写已知网址的网页?
    5-10 公路村村通 (30分)
  • 原文地址:https://www.cnblogs.com/Rosebud/p/9627003.html
Copyright © 2011-2022 走看看