Zoj 1610 Count the Colors (线段树+区间更新+暴力计数)
题目大意:
有n次操作,每次都是对一根线中的一段区间进行染色(颜色并不相同),有时候后面的颜色有可能覆盖前面的颜色,问最后涂完色,能看到的颜色有几种,每种颜色有几部分?
解题思路:
这个题目建树的时候有些不同,并不是以点为对象,而是以区间为对象,很明显是对线段树的区间进行操作,更新的时候要以区间为单位,还有就是计算每个区间出现几次的时候可以根据线段树的建树特征对树进行遍历求解。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 const int maxn = 8005; 7 struct node 8 { 9 int l, r, c; 10 int Mid() 11 { 12 return (r + l) / 2; 13 } 14 }; 15 node tree[maxn*4]; 16 int cnt[maxn], temp; 17 18 void Build (int root, int l, int r) 19 { 20 tree[root].l = l; 21 tree[root].r = r; 22 tree[root].c = -1; 23 if (l == r - 1) 24 return ; 25 Build (2*root+1, l, tree[root].Mid()); 26 Build (2*root+2, tree[root].Mid(), r); 27 } 28 void update (int root, int l, int r, int c) 29 {//区间更新, 30 if (l==tree[root].l && tree[root].r==r) 31 { 32 tree[root].c = c; 33 return ; 34 } 35 if (tree[root].c != -1) 36 { 37 tree[2*root+1].c = tree[2*root+2].c = tree[root].c; 38 tree[root].c = -1; 39 } 40 if (l >= tree[root].Mid()) 41 update (2*root+2, l, r, c); 42 else if (r <= tree[root].Mid()) 43 update (2*root+1, l, r, c); 44 else 45 { 46 update (2*root+1, l, tree[root].Mid(), c); 47 update (2*root+2, tree[root].Mid(), r, c); 48 } 49 } 50 void Count (int root) 51 { 52 if (tree[root].c != -1) 53 {//当前区间裸露在外面 54 if (tree[root].c != temp)//当前区间没有被统计过 55 cnt[tree[root].c] ++; 56 temp = tree[root].c; 57 return ; 58 } 59 if (tree[root].l == tree[root].r-1) 60 {//返回未被覆盖的区间,否则会栈溢出 61 temp = -1; 62 return ; 63 } 64 Count (2*root+1); 65 Count (2*root+2); 66 } 67 68 int main () 69 { 70 int n, m; 71 while (scanf ("%d", &n) != EOF) 72 { 73 Build (0, 0, maxn); 74 75 while (n --) 76 { 77 int x, y, c; 78 scanf ("%d %d %d", &x, &y, &c); 79 update (0, x, y, c); 80 } 81 temp = -1; 82 memset (cnt, 0, sizeof(cnt)); 83 Count(0); 84 for (int i=0; i<maxn; i++) 85 if (cnt[i]) 86 printf ("%d %d\n", i, cnt[i]); 87 printf ("\n"); 88 } 89 return 0; 90 }
本文为博主原创文章,未经博主允许不得转载。