POJ 2777 Count Color (线段树成段更新+二进制思维)
Posted Recoder
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 2777 Count Color (线段树成段更新+二进制思维)相关的知识,希望对你有一定的参考价值。
题目链接:http://poj.org/problem?id=2777
题意是有L个单位长的画板,T种颜色,O个操作。画板初始化为颜色1。操作C讲l到r单位之间的颜色变为c,操作P查询l到r单位之间的颜色有几种。
很明显的线段树成段更新,但是查询却不好弄。经过提醒,发现颜色的种类最多不超过30种,所以我们用二进制的思维解决这个问题,颜色1可以用二进制的1表示,同理,颜色2用二进制的10表示,3用100,...。假设有一个区间有颜色2和颜色3,那么区间的值为二进制的110(十进制为6)。那我们就把一个区间的颜色种类表示为(左孩子的值‘|’右孩子的值)。
然后就是一个线段树的成段更新。
有个坑点是这个题目的l可能比r大...
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 const int MAXN = 275000; 6 struct segtree { 7 int l , r , val , lazy; 8 }T[MAXN << 3]; 9 //获取颜色的种类 10 int get(int n) { 11 int cont = 0; 12 while(n) { 13 if(n & 1) 14 cont++; 15 n >>= 1; 16 } 17 return cont; 18 } 19 20 void init(int p , int l , int r) { 21 int mid = (l + r) >> 1; 22 T[p].l = l , T[p].r = r , T[p].lazy = 0; 23 if(l == r) { 24 T[p].val = 1; 25 return ; 26 } 27 init(p << 1 , l , mid); 28 init((p << 1)|1 , mid + 1 , r); 29 T[p].val = (T[p << 1].val | T[(p << 1)|1].val); 30 } 31 32 void updata(int p , int l , int r , int val) { 33 int mid = (T[p].l + T[p].r) >> 1; 34 if(l == T[p].l && T[p].r == r) { 35 T[p].val = val; 36 T[p].lazy = val; 37 return ; 38 } 39 if(T[p].lazy) { 40 T[p << 1].val = T[(p << 1)|1].val = T[p].lazy; 41 T[p << 1].lazy = T[(p << 1)|1].lazy = T[p].lazy; 42 T[p].lazy = 0; 43 } 44 if(r <= mid) { 45 updata(p << 1 , l , r , val); 46 } 47 else if(l > mid) { 48 updata((p << 1)|1 , l , r , val); 49 } 50 else { 51 updata(p << 1 , l , mid , val); 52 updata((p << 1)|1 , mid + 1 , r , val); 53 } 54 T[p].val = (T[p << 1].val | T[(p << 1)|1].val); 55 } 56 //返回颜色种类的二进制对应的十进制的值 57 int query(int p , int l , int r) { 58 int mid = (T[p].l + T[p].r) >> 1; 59 if(T[p].l == l && T[p].r == r) { 60 return T[p].val; 61 } 62 if(T[p].lazy) { 63 T[p << 1].val = T[(p << 1)|1].val = T[p].lazy; 64 T[p << 1].lazy = T[(p << 1)|1].lazy = T[p].lazy; 65 T[p].lazy = 0; 66 } 67 if(r <= mid) { 68 return query(p << 1 , l , r); 69 } 70 else if(l > mid) { 71 return query((p << 1)|1 , l , r); 72 } 73 else { 74 return query(p << 1 , l , mid) | query((p << 1)|1 , mid + 1 , r); 75 } 76 } 77 78 int main() 79 { 80 int L , t , n , l , r , c; 81 char str[5]; 82 while(~scanf("%d %d %d" , &L , &t , &n)) { 83 init(1 , 1 , L); 84 while(n--) { 85 scanf("%s" , str); 86 if(str[0] == ‘C‘) { 87 scanf("%d %d %d" , &l , &r , &c); 88 int temp = l + r; 89 l = min(l , r); 90 r = temp - l; 91 updata(1 , l , r , (1 << (c - 1))); 92 } 93 else { 94 scanf("%d %d" , &l , &r); 95 int temp = l + r; 96 l = min(l , r); 97 r = temp - l; 98 int res = get(query(1 , l , r)); 99 printf("%d\n" , res); 100 } 101 } 102 } 103 }
以上是关于POJ 2777 Count Color (线段树成段更新+二进制思维)的主要内容,如果未能解决你的问题,请参考以下文章
POJ 2777 Count Color (线段树 + 状态压缩)
POJ P2777 Count Color——线段树状态压缩
POJ - 2777——Count Color(懒标记线段树二进制)