zoj 1610 Count the Colors 【区间覆盖 求染色段】

Count the Colors


Time Limit: 2 Seconds     
Memory Limit: 65536 KB


Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent ones.

Your task is counting the segments of different colors you can see at last.

Input

The first line of each data set contains exactly one integer n, 1 <= n <= 8000, equal to the number of colored segments.

Each of the following n lines consists of exactly 3 nonnegative integers separated by single spaces:

x1 x2 c

x1 and x2 indicate the left endpoint and right endpoint of the segment, c indicates the color of the segment.

All the numbers are in the range [0, 8000], and they are all integers.

Input may contain several data set, process to the end of file.

Output

Each line of the output should contain a color index that can be seen from the top, following the count of the segments of this color, they should be printed according to the color index.

If some color can‘t be seen, you shouldn‘t print it.

Print a blank line after every dataset.

Sample Input

5

0 4 4

0 3 1

3 4 2

0 2 2

0 2 3

4

0 1 1

3 4 1

1 3 2

1 3 1

6

0 1 0

1 2 1

2 3 1

1 2 0

2 3 0

1 2 1

Sample Output

1 1

2 1

3 1

1 1

0 2

1 1


Author: Standlove

Source: ZOJ Monthly, May 2003

题意:在一条长度为8000的线段上染色,每次把区间[a,b]染成c颜色。

显然,后面染上去的颜色会覆盖掉之前的颜色。求染完之后,每种颜色在线段上有多少个间断的区间。

线段树Lazy区间改动。

让我无语的是——输出要求是按颜色编号从0到8000输出的。

而我傻傻的按插入顺序输出了1个小时。。

。o(╯□╰)o

AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 8000+10
using namespace std;
int color[MAXN<<2];//对节点染色
void PushDown(int o)
{
    if(color[o] != -1)
    {
        color[o<<1] = color[o<<1|1] = color[o];
        color[o] = -1;
    }
}
void update(int o, int l, int r, int L, int R, int v)
{
    if(L <= l && R >= r)
    {
        color[o] = v;
        return ;
    }
    PushDown(o);
    int mid = (l + r) >> 1;
    if(L <= mid)
        update(o<<1, l, mid, L, R, v);
    if(R > mid)
        update(o<<1|1, mid+1, r, L, R, v);
}
int rec[MAXN];//存储i节点的颜色
int top = 0;
void query(int o, int l, int r)
{
    if(l == r)
    {
        rec[top++] = color[o];//记录节点的颜色
        return ;
    }
    int mid = (l + r) >> 1;
    PushDown(o);
    query(o<<1, l, mid);
    query(o<<1|1, mid+1, r);
}
int num[MAXN];//记录颜色出现的 段数
int main()
{
    int N;
    while(scanf("%d", &N) != EOF)
    {
        memset(color, -1, sizeof(color));
        int a, b, c;
        for(int i = 1; i <= N; i++)
        {
            scanf("%d%d%d", &a, &b, &c);
            update(1, 1, 8000, a+1, b, c);//相应颜色数 先加一
        }
        memset(rec, -1, sizeof(rec));
        top = 0;//初始化
        query(1, 1, 8000);
        memset(num, 0, sizeof(num));//初始化
        int i, j;
        for(i = 0; i < top;)
        {
            if(rec[i] == -1)
            {
                i++;
                continue;
            }
            num[rec[i]]++;
            for(j = i + 1; j < top; j++)
            {
                if(rec[j] != rec[i] || rec[j] == -1)
                    break;
            }
            i = j;
        }
        for(int i = 0; i <= 8000; i++)
        {
            if(num[i])
                printf("%d %d\n", i, num[i]);
        }
        printf("\n");
    }
    return 0;
}

直接模拟也能够过:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <vector>
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MAXN (10000+10)
#define MAXM (50000000)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while(a--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
using namespace std;
int num[MAXN];
int color[MAXN];
int main()
{
    int n;
    while(Ri(n) != EOF)
    {
        int Max = -INF;
        CLR(color, -1);
        for(int i = 0; i < n; i++)
        {
            int x, y, c;
            Ri(x); Ri(y); Ri(c);
            Max = max(Max, c);
            for(int j = x; j < y; j++)
                color[j] = c;
        }
        CLR(num, 0);
        for(int i = 0; i <= 8000; )
        {
            int temp = color[i];
            if(temp == -1)
            {
                i++;
                continue;
            }
            i++;
            while(temp == color[i])
                i++;
            num[temp]++;
        }
        for(int i = 0; i <= Max; i++)
            if(num[i])
                printf("%d %d\n", i, num[i]);
        printf("\n");
    }
    return 0;
}

时间: 2024-10-25 08:47:15

zoj 1610 Count the Colors 【区间覆盖 求染色段】的相关文章

ZOJ 1610 Count the Colors(区间染色)

题目大意:多组数据,每组给一个n(1=<n<=8000),下面有n行,每行有l,r,color(1=<color<=8000),表示将l~r颜色变为color,最后求各种颜色(1~8000)所占区段数,如果所占区段为0则不用输出. 解题思路:基本还是跟区间染色问题差不多,但要注意一些东西 ①这里l,r指的是端点.比如 3 1 4 1 1 2 2 3 4 3 这组数据最后输出结果为: 1 1 2 1 3 1 原因是还有[2,3]这一段颜色为1,处理办法是将更新函数写成(1,l+1,r

ZOJ 1610 Count the Colors (线段树区间更新)

题目链接 题意 : 一根木棍,长8000,然后分别在不同的区间涂上不同的颜色,问你最后能够看到多少颜色,然后每个颜色有多少段,颜色大小从头到尾输出. 思路 :线段树区间更新一下,然后标记一下,最后从头输出. //ZOJ 1610 #include <cstdio> #include <cstring> #include <iostream> using namespace std ; int p[8010*4],lz[8010*4] ,hashh[8010*4],has

zoj 1610 Count the Colors

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=610 先用线段树维护区间颜色的覆盖,然后在把区间的颜色映射到数组,再从数组统计颜色. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define maxn 100000 5 using namespace std; 6 7 int n; 8 int min1; 9

ZOJ 1610 Count the Colors【题意+线段树区间更新&amp;&amp;单点查询】

任意门:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1610 Count the Colors Time Limit: 2 Seconds      Memory Limit: 65536 KB Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent

ZOJ 1610——Count the Colors——————【线段树区间替换、求不同颜色区间段数】

Count the Colors Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Submit Status Practice ZOJ 1610 Description Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent o

ZOJ 1610 Count the Colors(线段树,区间覆盖,单点查询)

Count the Colors Time Limit: 2 Seconds      Memory Limit: 65536 KB Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent ones. Your task is counting the segments of different colors you can s

ZOJ 1610 Count the Colors(线段树lazy+暴力统计)

Count the Colors Time Limit: 2 Seconds      Memory Limit: 65536 KB Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent ones. Your task is counting the segments of different colors you can s

ZOJ - 1610 Count the Colors 线段树区间修改

Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent ones. Your task is counting the segments of different colors you can see at last. InputThe first line of each data set contains exactly o

Zoj 1610 Count the Colors (线段树+区间更新+暴力计数)

题目大意: 有n次操作,每次都是对一根线中的一段区间进行染色(颜色并不相同),有时候后面的颜色有可能覆盖前面的颜色,问最后涂完色,能看到的颜色有几种,每种颜色有几部分? 解题思路: 这个题目建树的时候有些不同,并不是以点为对象,而是以区间为对象,很明显是对线段树的区间进行操作,更新的时候要以区间为单位,还有就是计算每个区间出现几次的时候可以根据线段树的建树特征对树进行遍历求解. 1 #include <cstdio> 2 #include <cstring> 3 #include