【线段树区间更新 && 染色】ZOJ

来源:互联网 发布:邮电大学网络教育 编辑:程序博客网 时间:2024/06/13 02:32

Problem Description

给你一个n,接下来n行,每行x1,x2,c代表将一维坐标轴上的x1-x2这段区间染色成颜色c,先画出来的可能会被后面画出来的覆盖掉。问你最后能看到的颜色和条数

思路:

区间更新,只需要lazy标记就好了。x1需要++,因为区间段少1。详细看代码

#include<bits/stdc++.h>using namespace std;#define lson root<<1#define rson root<<1|1#define MID int mid = (l + r) / 2;#define rls 1,1,8010#define N 8010int a[N * 4], color[N], vis[N];void pushdown(int root, int l, int r)//向下更新{    if(a[root] != -1)//有颜色    {        a[lson] = a[rson] = a[root];//向下更新颜色        a[root] = -1;    }}void updata(int root, int l, int r, int ul, int ur, int v){    if(ul <= l && r <= ur)    {        a[root] = v;        return ;    }    pushdown(root, l, r);    MID;    if(ul <= mid) updata(lson, l, mid, ul, ur, v);    if(ur > mid) updata(rson, mid + 1, r, ul, ur, v);}void dfs(int root, int l, int r)//将颜色向下更新。{    if(l == r)    {        color[l] = a[root];//color存最后1-N的颜色        return;    }    pushdown(root, l, r);    MID;    dfs(lson, l, mid);    dfs(rson, mid + 1, r);}int main(){    int n, i, ul, ur, v;    while(~scanf("%d", &n))    {        memset(a, -1, sizeof(a));//初始化-1,因为颜色是0开始        memset(color, -1, sizeof(color));//用来存最后1-N的颜色        memset(vis, 0, sizeof(vis));//后面记录颜色出现的条数        for(i = 0; i < n; i++)        {            scanf("%d %d %d", &ul, &ur, &v);            ul++;//细节            updata(rls, ul, ur, v);//区间更新ul-ur的颜色为v        }        dfs(rls);//将所有颜色pushdown到最底层。也就是1-N        for(i = 1; i <= N; i++)        {            if(color[i] != color[i - 1] && color[i] != -1)//颜色不一样同时有颜色。条数++            {                vis[color[i]]++;            }        }        for(i = 0; i <= N; i++)//输出就好了        {            if(vis[i])            {                printf("%d %d\n", i, vis[i]);            }        }        printf("\n");    }    return 0;}