题目地址: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 ",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 */