CC

自然万物都趋向从有序变得无序

0%

Count Color POJ 2777

题目链接:点我

题目


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

题意:

给你一块木板,木板可以分成L份,你有两种操作:1. 将A到B的所有木块涂成颜色C, 2. 查询A到B共有多少种不同的颜色.

思路:

线段树的区间查询以及更新,利用lazy的方法延迟更新.

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
using namespace std;

struct ss{
int l, r, color;
}a[400000];
bool sum[40];

void build(int cur, int l, int r){
a[cur].l = l;
a[cur].r = r;
a[cur].color = 1;//初始化颜色
if(l == r)
return ;
int mid = (l + r) >> 1;
build(cur << 1, l, mid);
build(cur << 1|1, mid + 1, r);
}

void update(int l, int r, int m, int cur){
if(a[cur].color == m) return ;
if(a[cur].l == l && a[cur].r == r){
a[cur].color = m;//如果区间完全符合,直接更新
return ;
}
if(a[cur].color != -1){//标记向下更新
a[cur << 1].color = a[cur << 1|1].color = a[cur].color;
a[cur].color = -1;
}
int mid = (a[cur].l + a[cur].r) >> 1;
if (l > mid) update( l, r, m ,cur << 1|1);
else if (r <= mid) update( l, r, m ,cur << 1);
else {
update( l, mid, m, cur << 1);
update( mid + 1, r, m, cur << 1|1);
}
}

void quiry(int l, int r, int cur){
if(a[cur].color != -1){
sum[a[cur].color] = true;
return;
}
int mid = (a[cur].l + a[cur].r) >> 1;
if(l > mid) quiry( l, r, cur << 1|1);
else if(r <= mid) quiry( l, r, cur << 1);
else {
quiry( l, mid, cur << 1);
quiry( mid + 1, r, cur << 1|1);
}
}

int main(){
int n,t,m;
while(scanf("%d %d %d", &n, &t, &m) !=EOF){
build( 1, 1, n);
while(m--){
char ch;
scanf(" %c", &ch);
if (ch == 'C'){
int x,y,z;
scanf("%d %d %d", &x, &y, &z);
update( x, y, z, 1);
}else{
memset(sum,false,sizeof(sum));//用数组记录有多少种不同的颜色
int x, y;
scanf("%d %d", &x, &y);
quiry( x, y, 1);
int ans = 0;
for(int i = 1; i <= 30; ++ i)
if (sum[i])
++ ans;
printf("%d\n", ans);
}
}
}
return 0;
}