Count Color poj 2777

题意:一个板,分成L段,开始板的每一段都被涂成颜色1。接下来对板有两种操作:

                        1. "C A B C" Color the board from segment A to segment B with color C. 
                        2. "P A B" Output the number of different colors painted between segment A and segment B (including).

题解:线段树+lazy.

思路:线段树的每个节点记录该段的颜色编号。叶节点记录该段的颜色,父亲节点记录该段的颜色。所以一开始建树时,所有节点的值都为1(整个板都是被涂成颜色1)。

当进行操作2时,进行更新线段树节点上的数据。首先判断在查找的区间范围内的颜色是否与将要涂的颜色相同,是----return(如果要涂的颜色与板上相应的区间颜色相同就没有必要再进行更新了),否----进行下一步,如果找到了要更新的区间,就把这个区间的节点改成相应的值,并标记lazy[]的值。这里要注意在查找更新区间时要把一路上所进过的节点都改成0,为什么?因为这些区间可能有两种或更多不同的颜色。也就是说凡是节点有大于0的值就代表确定这段区间只有一种颜色。

查找时,只要在查找的区间范围内,节点的值大于0,这段的颜色就记录在color[]数组里就可以了。最后枚举有多少个color即可。这里注意对lazy的操作。

 

AC代码:

View Code
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn=10000000;
 6 int L,T,O;
 7 int spt[maxn];
 8 int lazy[maxn];
 9 bool color[31];
10 void PushDown(int pos){
11     spt[pos*2]=lazy[pos];
12     lazy[pos*2]=lazy[pos];
13     spt[pos*2+1]=lazy[pos];
14     lazy[pos*2+1]=lazy[pos];
15     lazy[pos]=0;
16 }
17 void Build(int l,int r,int pos){
18     if(l==r){
19         spt[pos]=1;
20         return ;
21     }
22     int mid=(l+r)>>1;
23     Build(l,mid,pos*2);
24     Build(mid+1,r,pos*2+1);
25     spt[pos]=1;
26 }
27 void Updata(int l,int r,int c,int left,int right,int pos){
28     if(spt[pos]==c)return;
29     if(l<=left&&right<=r){
30         lazy[pos]=c;
31         spt[pos]=c;
32         return;
33     }
34     if(lazy[pos])PushDown(pos);
35     int mid=(left+right)>>1;
36     if(r<=mid)Updata(l,r,c,left,mid,pos*2);
37     else if(l>mid)Updata(l,r,c,mid+1,right,pos*2+1);
38     else{
39         Updata(l,r,c,left,mid,pos*2);
40         Updata(l,r,c,mid+1,right,pos*2+1);
41     }
42     spt[pos]=0;
43 }
44 void Query(int l,int r,int left,int right,int pos){
45     if(left==right){
46         color[spt[pos]]=true;
47         return;
48     }
49     if(l<=left&&right<=r&&spt[pos]){
50         color[spt[pos]]=true;
51         return;
52     }
53     if(lazy[pos])PushDown(pos);
54     int mid=(left+right)>>1;
55     if(r<=mid)Query(l,r,left,mid,pos*2);
56     else if(l>mid)      Query(l,r,mid+1,right,pos*2+1);
57     else{
58         Query(l,r,left,mid,pos*2);
59         Query(l,r,mid+1,right,pos*2+1);
60     }
61 }
62 void Swap(int &a,int &b){
63     int temp=a;
64     a=b;
65     b=temp;
66 }
67 int main()
68 {
69     //freopen("in.txt","r",stdin);
70     char s[2];
71     int a,b,c;
72     while(scanf("%d %d %d",&L,&T,&O)!=EOF){
73         memset(lazy,0,sizeof(lazy));
74         Build(1,L,1);
75         while(O--){
76             scanf("%s",s);
77             if(s[0]=='C'){
78                 scanf("%d %d %d",&a,&b,&c);
79                 if(a>b)Swap(a,b);
80                 Updata(a,b,c,1,L,1);
81             }
82             else{
83                 memset(color,false,sizeof(color));
84                 scanf("%d %d",&a,&b);
85                 if(a>b)Swap(a,b);
86                 Query(a,b,1,L,1);
87                 int ans=0;
88                 for(int i=1;i<=30;i++)
89                     if(color[i])ans++;
90                 printf("%d\n",ans);
91             }
92         }
93     }
94     return 0;
95 }

 

posted on 2012-10-17 13:02  Acmer_Roney  阅读(181)  评论(0编辑  收藏  举报

导航