Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 33098 | Accepted: 9995 |
Descriptionios
Inputexpress
Outputide
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 }
附一组测试数据:
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