ZOJ

题意:m次询问给你区间段的颜色,然后区间修改颜色覆盖,统计最后各种颜色出现的段数

思路:就是线段树比较基本的操作,区间修改,再把区间所有的值赋值给统计数组,然后统计段个数

完整代码:

#include <cstdio>
#include <cstring>
const int maxn = 8000 ; 
const int N = 8010 << 2;
int n;
int color[N], segment[N], ans[N];

void PushDown(int u) {
    
    if (color[u] != -1) {
        color[u << 1] = color[u << 1 | 1] = color[u];
        color[u] = -1;
    }
}

void modify(int u, int l, int r, int L, int R, int c) {

    if (L <= l && r <= R) {
        color[u] = c;
        return ;
    }
    if (color[u] == c) return ;
    PushDown(u);
    int mid = (l + r) >> 1;
    if (L <= mid) modify(u << 1, l, mid, L, R, c);
    if (R > mid) modify(u << 1 | 1, mid + 1, r, L, R, c);
}

void query(int u, int l, int r) {
    //这一次query即是把从1到n的color复制到segment里面 
    if (color[u] != -1) {
        for (int i = l; i <= r; i++)
            segment[i] = color[u];
        return ;
    }
    if (l == r) return ;
    int mid = (l + r) >> 1;
    query(u << 1, l, mid);
    query(u << 1 | 1, mid + 1, r);
}


int main() {
    while (~scanf("%d", &n)){
        memset(color, -1, sizeof(color));
           memset(segment, -1, sizeof(segment));
        memset(ans, 0, sizeof(ans));
        int a, b, c;
        while (n--) {
            scanf("%d%d%d", &a, &b, &c);
            if (a >= b) continue;
            modify(1, 1, maxn, a + 1, b, c);
        }
        query(1, 1, maxn);
        
        int i = 1;
        while (i <= maxn) {
            int c = segment[i], j = i + 1;
            if (c == -1) {
                i++; 
                continue;
            }
            while (segment[j] == c && j <= maxn) j++;
            ans[c]++;
            i = j;
        }
        for (int i = 0; i <= maxn; i++)
            if (ans[i]) printf("%d %d
", i, ans[i]);
        printf("
");    
        } 

    return 0;
}
原文地址:https://www.cnblogs.com/Tianwell/p/11297475.html