POJ 2777 Count Color 线段树
题目: http://poj.org/problem?id=2777
虽然是简单题,但是我还是写一下我的理解。
插入和查询都是自上而下进行的,所以如果当前线段是红色的,那么子节点肯定也是红色的,不必继续往下遍历,这便是lazy的核心。
所以我们要标记一段线段是否是纯色的,这个题颜色用1-30来表示,所以我用0表示非纯色,非纯色时要继续遍历子节点。
当需要插入当前线段的子线段时,如果当前线段是纯色的,先把当前线段的颜色赋给左右子线段,然后标记当前线段为非纯色(即0),然后继续递归插入子线段,这样就成功降低了时间复杂度。
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 5 const int MAXN = 100010; 6 bool flag[35]; 7 8 struct Tree_Node 9 { 10 int left, right; 11 int color; 12 } tree[MAXN<<2]; 13 14 void build(int left, int right, int step) 15 { 16 tree[step].left = left; 17 tree[step].right = right; 18 tree[step].color = 1; 19 if(left == right) 20 { 21 return; 22 } 23 int mid = (left + right) >> 1; 24 build(left, mid, step<<1); 25 build(mid+1, right, step<<1|1); 26 } 27 28 void insert(int left, int right, int color, int step) 29 { 30 int mid = (tree[step].left + tree[step].right) >> 1; 31 if(tree[step].left == left && tree[step].right == right) 32 { 33 tree[step].color = color; 34 return; 35 } 36 if(tree[step].color == color) 37 return; 38 if(tree[step].color > 0) 39 { 40 tree[step<<1].color = tree[step<<1|1].color = tree[step].color; 41 tree[step].color = 0; 42 } 43 if(right <= mid) 44 { 45 insert(left, right, color, step<<1); 46 } 47 else if(left > mid) 48 { 49 insert(left, right, color, step<<1|1); 50 } 51 else 52 { 53 insert(left, mid, color, step<<1); 54 insert(mid+1, right, color, step<<1|1); 55 } 56 } 57 58 void query(int left, int right, int step) 59 { 60 int mid = (tree[step].left + tree[step].right) >> 1; 61 if(tree[step].color > 0) 62 { 63 flag[tree[step].color] = 1; 64 return; 65 } 66 if(right <= mid) 67 { 68 query(left, right, step<<1); 69 } 70 else if(left > mid) 71 { 72 query(left, right, step<<1|1); 73 } 74 else 75 { 76 query(left, mid, step<<1); 77 query(mid+1, right, step<<1|1); 78 } 79 } 80 81 int main() 82 { 83 int l, m, n; 84 int left, right, color; 85 char cmd[2]; 86 scanf("%d %d %d", &l, &m, &n); 87 build(1, l, 1); 88 while(n--) 89 { 90 scanf("%s", cmd); 91 if(cmd[0] == 'C') 92 { 93 scanf("%d %d %d", &left, &right, &color); 94 if(left > right) 95 std::swap(left, right); 96 insert(left, right, color, 1); 97 } 98 else 99 { 100 scanf("%d %d", &left, &right); 101 if(left > right) 102 std::swap(left, right); 103 memset(flag, 0, sizeof(flag)); 104 query(left, right, 1); 105 int ans = 0; 106 for(int i = 1; i <= m; i++) 107 { 108 ans += flag[i]; 109 } 110 printf("%d\n", ans); 111 } 112 } 113 return 0; 114 }