ZOJ 1610 Count the Colors

经典的线段上色问题,略有不同的地方时从0开始,还有要输出每种颜色的个数 。

题目:线段染色问题,求最后最上面的颜色段数

思路:对每一次染色执行update操作,当颜色未完全覆盖当前段时,当前根的颜色块需要下移!然后执行一次query操作记录所有线段的颜色

法一:

 1 #include<stdio.h>
 2  #include<string.h>
 3  #define N 8001
 4  int color[N],cnt[N];//这个cnt是用来记录颜色i出现的段数 ,注意cnt里的这个N真的需要好大,我以为就几百种呢,结果WA好多次 
 5  int main()
 6  {
 7      int i,j,a,b,c,max,n;
 8      while(~scanf("%d",&n)){
 9          for(max=i=0;i<n;++i){
10              scanf("%d%d%d",&a,&b,&c);
11              for(j=a;j<b;++j)
12                  color[j]=c+1;
13              if(max<b) max=b;
14          }
15          for(i=0;i<max;++i){
16              while(i!=0&&color[i]&&color[i]==color[i-1]) //假如颜色不为空且与前一段相同,则继续读下一段 
17                  ++i;
18              if(color[i])
19                  cnt[color[i]-1]++;  //颜色为color[i]-1的段数加一 
20          }
21          for(i=0;i<N;++i)
22          if(cnt[i]) printf("%d %d\n",i,cnt[i]);//从小到大输出颜色及出现次数 
23          memset(color,0,max*sizeof(int));//记得清空 
24          memset(cnt,0,sizeof(cnt));
25          putchar('\n');
26      }
27      return 0;
28  }

法二:

1。创建线段树

    1)取最小和最大的两个数作为端点,建立线段树

    2)当前节点的两个端点值之差等于一时,此时该节点即位叶子节点,不用再 向下分

    3)否则,分裂该节点为[a,(a + b) / 2], [(a + b) / 2, b];

    4)创建线段树时,注意初始化操作

2。线段树着色(根据不同的题目此操作各不相同,对zju_1610做分析)

    1)当前节点的颜色与将要涂的颜色color相同,直接return

    2)当前线段树节点的两个端点和要涂的两个端点正好都相同,则将该节点着为color,然后return

    3)要涂的两个端点在当前节点的两个端点之间时:先将当前节点的颜色向其子节点扩展,然后:

       1.要涂的右端点小于或等于当前节点middle = (a + b) / 2时,向左子节点移动

       2.要涂的左端点大于或等于当前节点middle = (a + b) / 2时,向右子节点移动

       3.else (1 ,2)向左右子节点移动

3。相关统计

   1)当前节点未着色或其颜色与要统计的颜色不相同,直接return

   2)从0——8000依次扫描,如果还是原来的数,即还是一条颜色,那么 continue,不计,是其他颜色,ans[c]++;

  1 #include <iostream>
  2 #include <string>
  3 using namespace std;
  4 #define MAX 8000
  5 struct Node
  6 {
  7     int l,r;
  8     int c;
  9 };
 10 Node tree[MAX*4];
 11 int ans[MAX+10];
 12 int seg[MAX+10];
 13 void Initial(int i,int l, int r,int c)
 14 {
 15     if(l>=r )
 16         return;
 17     tree[i].l = l;
 18     tree[i].r = r;
 19     tree[i].c = c;
 20     if(r - l == 1)
 21         return;
 22     int mid = (tree[i].l+tree[i].r) >> 1;
 23     Initial(i*2,l,mid,c);
 24     Initial(i*2+1,mid,r,c);
 25 }
 26 void add(int i,int l,int r,int c)
 27 {
 28     if(c == tree[i].c)
 29     {
 30         return ;
 31     }
 32     if(l == tree[i].l && r == tree[i].r)
 33     {
 34             tree[i].c = c;
 35 
 36     }else
 37     {
 38         int mid = (tree[i].l + tree[i].r) >> 1;
 39          if(tree[i].c >= 0)
 40          {
 41             tree[i*2].c = tree[i].c;
 42             tree[i*2+1].c = tree[i].c;
 43          }
 44           tree[i].c = -1;
 45         if(l >= mid)
 46         {
 47             add(i*2+1,l,r,c);
 48         }
 49         else
 50             if(r <= mid)
 51             {
 52                 add(i*2,l,r,c);
 53             }else
 54             {
 55 
 56                 add(i*2,l,mid,c);
 57                 add(i*2+1,mid,r,c);
 58             }
 59         if(tree[i*2].c == tree[i*2+1].c)
 60         {
 61         tree[i].c = tree[i*2].c;
 62         }
 63     }
 64 }
 65 void counts(int i)
 66 {
 67     if(tree[i].c != -1)
 68     {
 69         for(int j = tree[i].l; j <= tree[i].r;j++)
 70         {
 71             seg[j] = tree[i].c;
 72         }
 73     }
 74     else
 75     {
 76         counts(i*2);
 77         counts(i*2+1);
 78     }
 79 }
 80 void total()
 81 {
 82     int c = seg[0];
 83     for(int i = 0;i <= MAX;i++)
 84     {
 85         if(seg[i]==c)
 86         continue;
 87         if(c >= 0) ans[c] ++;
 88         c= seg[i];
 89 
 90     }
 91     if(c >= 0) ans[c] ++;
 92 }
 93 int main() {
 94     freopen("in","r",stdin);
 95     int i,n,x,y,c;
 96 
 97     while(scanf("%d",&n) != EOF)
 98     {
 99         Initial(1,0,MAX,-2);
100         memset(ans,0,sizeof(ans));
101 
102         while(n--)
103         {
104             scanf("%d %d %d",&x,&y,&c);
105             add(1,x,y,c);
106         }
107         counts(1);
108         total();
109         for(i = 0; i <= MAX; i++)
110         {
111             if(ans[i])
112             {
113                 printf("%d %d/n",i,ans[i]);
114             }
115         }
116         printf("/n");
117     }
118     return 0;
119 }

 

 

posted on 2012-08-10 11:19  mycapple  阅读(280)  评论(0)    收藏  举报

导航