zoukankan      html  css  js  c++  java
  • POJ 2777 Count Color

    Count Color
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 33098   Accepted: 9995

    Description

    Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem. 

    There is a very long board with length L centimeter, L is a positive integer, so we can evenly divide the board into L segments, and they are labeled by 1, 2, ... L from left to right, each is 1 centimeter long. Now we have to color the board - one segment with only one color. We can do following two operations on the board: 

    1. "C A B C" Color the board from segment A to segment B with color C. 
    2. "P A B" Output the number of different colors painted between segment A and segment B (including). 

    In our daily life, we have very few words to describe a color (red, green, blue, yellow…), so you may assume that the total number of different colors T is very small. To make it simple, we express the names of colors as color 1, color 2, ... color T. At the beginning, the board was painted in color 1. Now the rest of problem is left to your. 

    Input

    First line of input contains L (1 <= L <= 100000), T (1 <= T <= 30) and O (1 <= O <= 100000). Here O denotes the number of operations. Following O lines, each contains "C A B C" or "P A B" (here A, B, C are integers, and A may be larger than B) as an operation defined previously.

    Output

    Ouput results of the output operation in order, each line contains a number.

    Sample Input

    2 2 4
    C 1 1 2
    P 1 2
    C 2 2 2
    P 1 2
    

    Sample Output

    2
    1
    

    Source

    这题第一次交的时候还是2013年1月,过了一年多,终于把它给过了。

    其实就是一道比较简单的线段树问题。

    题目的意思是说,给一条长为L的板子,在上面进行两种操作:P a b c表示将板上[a,b]区间内染为c色,C a b表示询问在板上[a,b]区间内有多少种不同的颜色

    做法就是线段树啦,树中每个结点维护两个信息,Color[k]记录结点k所表示的区间[l,r]上所染的颜色,End[k]=true意味着k结点所表示的区间[l,r]之间的颜色就是Color[k],不用再向下更新和查询了,而End[k]=false则意味着k结点所表示的区间[l,r]之间的颜色并不是Color[k],而要在它的两了儿子结点中继续查询。

    更细节的部分参风代码中的注释,很详细的~~

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 
     6 using namespace std;
     7 
     8 int L, T, O, a, b, c;
     9 int color[500000];
    10 bool End[500000], haveColor[35];
    11 
    12 //线段树的染色操作,将[x,y)区间染为c色,当前操作结点为k,所表示的区间为[l,r)
    13 void PaintColor(int c, int x, int y, int k, int l, int r)
    14 {
    15     //若区间[x,y)和[l,r)完全没有交集,则直接返回
    16     if (y <= l || x >= r)
    17         return;
    18     //若区间[x,y)完全覆盖了区间[l,r),则将结点k染为c色,并将End[k]置为true
    19     if (x <= l&&r <= y)
    20     {
    21         color[k] = c;
    22         End[k] = true;
    23         return;
    24     }
    25 
    26     //其它情况:区间[x,y)与区间[l,r)只有部分交集
    27     //若区间[l,r)之间的染色为Color[k](即End[k]=true),则要先将当前区间的颜色传递下去
    28     if (End[k])
    29     {
    30         PaintColor(color[k], l, r, k * 2 + 1, l, (l + r) / 2);
    31         PaintColor(color[k], l, r, k * 2 + 2, (l + r) / 2, r);
    32         End[k] = false;
    33     }
    34     //递归地染色左儿子结点和右儿子结点
    35     PaintColor(c, x, y, k * 2 + 1, l, (l + r) / 2);
    36     PaintColor(c, x, y, k * 2 + 2, (l + r) / 2, r);
    37 }
    38 
    39 //查询区间[x,y)之间有多少种不同的颜色,当前操作的结点为k,表示的区间为[l,r)
    40 void CountColor(int x, int y, int k, int l, int r)
    41 {
    42     //若区间[x,y)和[l,r)完全没有交集,则直接返回
    43     if (y <= l || x >= r)
    44         return;
    45     //若End[k]=true,则无需再向这个结点的子结点进行查询,直接标记之后返回即可
    46     if (End[k])
    47     {
    48         haveColor[color[k]] = true;
    49         return;
    50     }
    51     //其它情况,递归地查询k结点的左右儿子结点
    52     CountColor(x, y, k * 2 + 1, l, (l + r) / 2);
    53     CountColor(x, y, k * 2 + 2, (l + r) / 2, r);
    54 }
    55 
    56 int main()
    57 {
    58     while (scanf("%d %d %d", &L, &T, &O) == 3)
    59     {
    60         memset(End, false, sizeof(End));
    61         PaintColor(1, 1, L + 1, 0, 1, L + 1);
    62 
    63         char ch;
    64         for (int k = 1; k <= O; k++)
    65         {
    66             getchar();
    67             ch = getchar();
    68             scanf("%d %d", &a, &b);
    69             if (a > b)
    70                 swap(a, b);
    71             if (ch == 'C')
    72             {
    73                 scanf("%d", &c);
    74                 PaintColor(c, a, b + 1, 0, 1, L + 1);
    75             }
    76             else if (ch == 'P')
    77             {
    78                 memset(haveColor, false, sizeof(haveColor));
    79                 CountColor(a, b + 1, 0, 1, L + 1);
    80                 int ans = 0;
    81                 for(int i=1;i<=T;i++)
    82                     if (haveColor[i])
    83                         ans++;
    84                     printf("%d
    ", ans);
    85             }
    86         }
    87     }
    88 
    89     return 0;
    90 }
    [C++]

    附一组测试数据:

    Input:

    10 4 5
    C 2 1 3
    C 9 10 2
    C 5 5 4
    P 1 5
    P 2 2

    12 5 10
    C 3 2 4
    C 5 4 2
    P 6 5
    C 1 2 2
    C 2 3 2
    C 4 4 1
    P 2 3
    P 7 7
    C 8 12 5
    P 1 12

    6 7 4
    C 1 6 2
    P 1 5
    C 4 2 7
    P 6 1

    Output:

    3
    1

    2
    1
    1
    3

    1
    2

  • 相关阅读:
    logback配置模板
    mail
    jpa,querydsl
    加密签名
    angular2快速开始
    主从复制
    随笔
    缺货源的小伙伴们 我发现一个超级好的货源供应链 分享给大家
    canal+kafka+logstash+es 架构 logstash的配置
    golang 根据图片url获取图片尺寸
  • 原文地址:https://www.cnblogs.com/lzj-0218/p/3585242.html
Copyright © 2011-2022 走看看