POJ 2777 Count Color

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

Descriptionios

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. 

Inputexpress

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.

Outputide

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 Outputui

2
1

Sourcespa

 

這題第一次交的時候仍是2013年1月,過了一年多,終於把它給過了。rest

其實就是一道比較簡單的線段樹問題。code

題目的意思是說,給一條長爲L的板子,在上面進行兩種操做:P a b c表示將板上[a,b]區間內染爲c色,C a b表示詢問在板上[a,b]區間內有多少種不一樣的顏色blog

作法就是線段樹啦,樹中每一個結點維護兩個信息,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\n", 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

12

相關文章
相關標籤/搜索