zoukankan      html  css  js  c++  java
  • 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

    昨天看POJ上的提交记录,已经整整三个月没有做过题了,真是堕落啊。。。

    今天复习线段树,写了这个染色问题。

    重点就是加入一个bool变量做为标志,这样在更新和查询的时候都不用一直查到叶子结点,这样大大提高效率。

    思路在代码中有详细注释

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 
      5 using namespace std;
      6 
      7 typedef struct
      8 {
      9     int left,right;
     10     int color;
     11     bool End;
     12 } NODE;
     13 
     14 typedef struct
     15 {
     16     int left,right;
     17     int color;
     18 }SEGMENT;
     19 
     20 int t;
     21 int color[10000];
     22 NODE node[40000];
     23 SEGMENT segment[10000];
     24 
     25 //对线段树进行初始化
     26 void initial(int root,int l,int r)
     27 {
     28     node[root].left=l;
     29     node[root].right=r;
     30     if(l<r-1)
     31     {
     32         initial(root*2+1,l,(l+r)/2);
     33         initial(root*2+2,(l+r)/2,r);
     34     }
     35 }
     36 
     37 //对线段树进行染树,root为根节点,l和r为染色范围,color为染的颜色
     38 void paint(int root,int l,int r,int color)
     39 {
     40     //如果染色范围与根节点没有交集,则直接返回
     41     if(l>=node[root].right||r<=node[root].left)
     42         return ;
     43 
     44     //如果根节点的范围被染色范围完全包围,则将根节点染色并将此结点标记为true(即查询时到这里为止)
     45     if(l<=node[root].left&&r>=node[root].right)
     46     {
     47         node[root].color=color;
     48         node[root].End=true;
     49     }
     50     else  //根节点的范围与染色范围只胡部分交集时
     51     {
     52         //若根节点之前标记为true,则先将根节点的颜色递归地染到它的子树上去,然后将根节点改为false
     53         if(node[root].End)
     54         {
     55             paint(root*2+1,node[root].left,(node[root].left+node[root].right)/2,node[root].color);
     56             paint(root*2+2,(node[root].left+node[root].right)/2,node[root].right,node[root].color);
     57             node[root].End=false;
     58         }
     59         //如果根节点的范围与染色范围只在左儿子部分重合,则只需递归地染色左孩子
     60         if(r<=(node[root].left+node[root].right)/2)
     61             paint(root*2+1,l,r,color);
     62         //如果根节点的范围与染色范围只在右儿子部分重合,则只需递归地染色右孩子
     63         else if(l>=(node[root].left+node[root].right)/2)
     64             paint(root*2+2,l,r,color);
     65         //如果染色范围与左右孩子都有重合,则需要递归地染色左右孩子
     66         else
     67         {
     68             paint(root*2+1,l,(node[root].left+node[root].right)/2,color);
     69             paint(root*2+2,(node[root].left+node[root].right)/2,r,color);
     70         }
     71     }
     72 }
     73 
     74 //查询函数,root为要查询的根节点
     75 void dfs(int root)
     76 {
     77     //如果根节点的End为false则还要递归地查询它的左右孩子
     78     if(!node[root].End)
     79     {
     80         dfs(root*2+1);
     81         dfs(root*2+2);
     82     }
     83     //如果根节点的End为true则可以停止递归并记录下这次染色
     84     else
     85     {
     86         if(node[root].color!=-1)
     87         {
     88             segment[t].left=node[root].left;
     89             segment[t].right=node[root].right;
     90             segment[t].color=node[root].color;
     91             t++;
     92         }
     93     }
     94 }
     95 
     96 int main()
     97 {
     98     int n;
     99 
    100     //建立线段树
    101     initial(0,0,8000);
    102 
    103     while(scanf("%d",&n)==1)
    104     {
    105         //初始化线段树的根节点,最初没有染过色,所以根节点End=true,颜色color=-1表示没有染色
    106         node[0].End=true;
    107         node[0].color=-1;
    108 
    109         int x1,x2,c;
    110 
    111         //读入数据并染色
    112         for(int i=1;i<=n;i++)
    113         {
    114             scanf("%d %d %d",&x1,&x2,&c);
    115             paint(0,x1,x2,c);
    116         }
    117 
    118         t=0;
    119 
    120         //查询每段的染色状况
    121         dfs(0);
    122 
    123         //处理查询结果,合并相邻且相同颜色的线段,求出共有多少条线段
    124         for(int i=0;i<10000;i++)
    125             color[i]=0;
    126         color[segment[0].color]=1;
    127 
    128         for(int i=1;i<t;i++)
    129         {
    130             if(segment[i].color==segment[i-1].color&&segment[i].left==segment[i-1].right)
    131                 continue;
    132             color[segment[i].color]++;
    133         }
    134 
    135         //输出结果
    136         for(int i=0;i<10000;i++)
    137             if(color[i])
    138                 printf("%d %d
    ",i,color[i]);
    139 
    140         printf("
    ");
    141     }
    142 
    143     return 0;
    144 }
    [C++]
  • 相关阅读:
    acm入门 杭电1001题 有关溢出的考虑
    面向对象课后深入学习(C++ 类的静态成员详细讲解)
    Eclipse中导入项目后js报错解决方法
    mysql用户链接数
    配置服务器nginx 教程
    eclipse如何新建项目发布到git
    获取当天开始时间结束时间
    pdf在线加载·
    springmvc配置详解 教程
    hibulder中使用git教程
  • 原文地址:https://www.cnblogs.com/lzj-0218/p/3458222.html
Copyright © 2011-2022 走看看