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 }
View Code

 

posted @ 2013-11-05 21:06  Anti-Magic  阅读(180)  评论(0编辑  收藏  举报