poj2777( Count Color)

题目地址:Count Color

 

题目大意:

      给一个划分为L的线段染色,有两种操作,一种C操作 给定l,r区间染色为val。另一种操作P 查询l,r区间的颜色有多少种。

 

解题报告:

      线段树,区间更新。

这题的lazy 表示该区间颜色种类,如果单色则为“1”,如果多色为”0“。tag 代表该区间的哪一种颜色。如果修改区间的颜色时,判断修改的颜色和该区间的颜色是否相同,相同的话就return,如果直接找到该区间,直接lazy赋值为”1“,tag 赋值为”v“,不用往下递归,因为该区间包含下面的子区间的单色,所以查询的时候,只需要看从根区间往下递归,只要遇到单色区间,就说明往下的子区间也就一定是该颜色。

 注意:线段数核心查询区间,不要访问到每个叶子节点会TLE。

         线段数被调里尽量不要有循环会TLE。(这题在建树和updata里插了了31的循环就TLE了)

         注意线段树从大区间往下分离成两个小区间,如果是染色,查到大区间的染色情况单色就能确定以下子区间的染色,否则往下递归继续查询。

         注意lazy的使用。

代码:

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <sstream>
  4 #include <cstdlib>
  5 #include <cstring>
  6 #include <cstdio>
  7 #include <string>
  8 #include <bitset>
  9 #include <vector>
 10 #include <queue>
 11 #include <stack>
 12 #include <cmath>
 13 #include <list>
 14 #include <map>
 15 #include <set>
 16 using namespace std;
 17 /***************************************/
 18 #define ll long long
 19 #define int64 __int64
 20 /***************************************/
 21 const int INF = 0x7f7f7f7f;
 22 const double eps = 1e-8;
 23 const double PIE=acos(-1.0);
 24 const int d1x[]= {0,-1,0,1};
 25 const int d1y[]= {-1,0,1,0};
 26 const int d2x[]= {0,-1,0,1};
 27 const int d2y[]= {1,0,-1,0};
 28 const int fx[]= {-1,-1,-1,0,0,1,1,1};
 29 const int fy[]= {-1,0,1,-1,1,-1,0,1};
 30 /***************************************/
 31 void openfile()
 32 {
 33     freopen("data.in","rb",stdin);
 34     freopen("data.out","wb",stdout);
 35 }
 36 /**********************华丽丽的分割线,以上为模板部分*****************/
 37 const int M=100100;
 38 
 39 struct tree
 40 {
 41     int left,right;
 42     int lazy,tag; //lazy储存该区间的颜色是否单色,单色为1 多色为0
 43                   //tag 记录该区间的颜色为哪种
 44 } node[M*4];
 45 
 46 int cnt;
 47 int p[31];
 48 void build__tree(int id,int l,int r)
 49 {
 50     int mid=(l+r)/2;
 51     node[id].lazy=1;
 52     node[id].tag=1;
 53     node[id].left=l;
 54     node[id].right=r;
 55     if (l==r)
 56         return ;
 57     build__tree(id*2,l,mid);
 58     build__tree(id*2+1,mid+1,r);
 59 }
 60 void updata(int id,int l,int r,int v)
 61 {
 62     int mid=(node[id].left+node[id].right)/2;
 63     if (node[id].left==l&&node[id].right==r)//区间染色
 64     {
 65         node[id].lazy=1;
 66         node[id].tag=v;
 67         return ;
 68     }
 69     if (node[id].tag==v&&node[id].lazy)  //如果该区间和即将染色的区间颜色相同,并且单色则不用进行
 70         return ;
 71     if (node[id].lazy) // 单色且染色不同,需要进行lazy操作
 72     {
 73         node[id].lazy=0; //标记多色
 74         updata(id*2,node[id].left,mid,node[id].tag);
 75         updata(id*2+1,mid+1,node[id].right,node[id].tag);
 76     }
 77     if (r<=mid)
 78         updata(id*2,l,r,v);
 79     else if (l>mid)
 80         updata(id*2+1,l,r,v);
 81     else
 82     {
 83         updata(id*2,l,mid,v);
 84         updata(id*2+1,mid+1,r,v);
 85     }
 86 }
 87 void query(int id,int l,int r)
 88 {
 89     int mid=(node[id].left+node[id].right)/2;
 90     if (node[id].lazy)  //该区间为单色,说明子区间为同样颜色。
 91     {
 92         p[node[id].tag]=1;
 93         return;
 94     }
 95     if (r<=mid)
 96         query(id*2,l,r);
 97     else if (l>mid)
 98         query(id*2+1,l,r);
 99     else
100     {
101         query(id*2,l,mid);
102         query(id*2+1,mid+1,r);
103     }
104 }
105 int main()
106 {
107     int l,t,o;
108     while(scanf("%d%d%d",&l,&t,&o)!=EOF)
109     {
110         int i,j;
111         build__tree(1,1,l);
112         while(o--)
113         {
114             char c;
115             int x,y,val;
116             getchar();
117             scanf("%c",&c);
118             if (c=='C')
119             {
120                 scanf("%d%d%d",&x,&y,&val);
121                 if (x>y)
122                     swap(x,y);
123                 updata(1,x,y,val);
124             }
125             if (c=='P')
126             {
127                 cnt=0;
128                 memset(p,0,sizeof(p));
129                 scanf("%d%d",&x,&y);
130                 if (x>y)
131                     swap(x,y);
132                 query(1,x,y);
133                 for(int i=1;i<31;i++)
134                     if (p[i])
135                         cnt++;
136                 printf("%d\n",cnt);
137             }
138         }
139 
140     }
141     return 0;
142 }
143 
144 /*
145 2 2 100
146 C 1 1 2
147 P 1 2
148 C 2 2 2
149 P 1 2
150 C 2 2 2
151 P 1 2
152 C 1 1 2
153 P 1 2
154 C 1 2 2
155 P 1 2
156 C 1 2 1
157 
158 5 3 1000
159 C 2 3 2
160 C 2 4 3
161 C 3 5 2
162 C 2 3 1
163 C 1 3 2
164 P 1 5
165 
166 5 3 1000
167 P 1 5
168 C 2 3 2
169 P 1 5
170 C 2 4 3
171 P 1 5
172 C 3 5 2
173 P 1 5
174 C 2 3 1
175 P 1 5
176 C 1 3 2
177 P 1 5
178 C 4 4 3
179 P 1 5
180 */
View Code

 

posted @ 2014-11-04 11:59  kinghold  Views(139)  Comments(0Edit  收藏  举报