标签:
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 42472 | Accepted: 12850 |
Description
Input
Output
Sample Input
2 2 4 C 1 1 2 P 1 2 C 2 2 2 P 1 2
Sample Output
2 1
Source
讲讲题目大意(反正很多单词我也不懂)
有一个板子长L厘米,以1cm为单位进行涂色,一共有T种颜色,木板初始的颜色是
编号为1的颜色(颜色编号从1标到T),有o个操作,操作分两种
1. "C A B C" 将[a,b]涂成颜色C(涂色是覆盖)
2. "P A B" 输出[a,b]不同的颜色
初看这道题觉得可能是用线段树做,于是想出了如下几个问题
1.每个区间存储什么?
2.pushUp和pushDown怎么更新
第一问比较好解决,就存颜色的信息,如果说存颜色的种数(查完就完了),有一
个很严重的问题,两个区间的颜色可能会有重复,更新的时候还要去判重,显得十分地
麻烦,干脆直接存各种颜色的是否在这个区间存在
这样就好了,定个bool数组,更新的时候就合并,另外又出现了一个无法避免的问题——
超内存、超时(时间限制是1s!),bool类型是1字节,等于8二进制位,是不是有点过于浪费
内存。那就把它分割一下,分成4个bool类型,这样,究竟用哪一个呢?这样貌似又要浪费代码。
反正T也不大,也就30,于是我想到了int...
就这样第一问就解决了,那怎么更新呢?总不可能相加,位运算中有一个运算是|(或运算)
这样用起来快,也方便,比如有两个区间它们的涂色情况如下:
//假设有4种颜色 [1,3] 0 1 1 0 [4,5] 1 0 1 0
通过or运算后:
[1,5] 1 1 1 0
都不用考虑重复的问题了
pushUp就用这个来,将左右子树上的颜色信息相or就得到了父节点的颜色信息
结合则来考虑一下pushDown ,查询区间的时候,应该是把节点上的区间完全
覆盖的情况下才会更改延时更新,所以这个区间下的“子区间”颜色信息应该是一样的,
并且只有这一种颜色如果延时标记记录颜色的编号的话,那么应该这么向下更新
node->xxx->painted = 1 << (node->state - 1)
(xxx表示左子树或者右子树,state是延时标记,painted是颜色信息)
如果不知道左移运算的可以看看下面
a = 0 0 0 0 1
当 a <<= 2后:
a << 2 = 0 0 1 0 0
那如果a<<31会发生什么?
a = 0 0 0 0 0
如果超过了它的二进制位这几位就没有了
这里左移的意义在于将1(有这种颜色)移动到这种颜色对应的位置上,不然会发生可怕
的事情
这些问题解决了,这道题也就可以做出来了
附上算得超级慢的源代码:
1 /** 2 * poj.org 3 * Problem#2777 4 * Aceepted 5 * Time:735ms 6 * Memory:9628k 7 */ 8 #include<iostream> 9 #include<cstdio> 10 using namespace std; 11 typedef class TreeNode{ 12 private: 13 void init(){ //成员初始化 14 painted = 0; 15 state = 0; 16 left = NULL; 17 right = NULL; 18 } 19 public: 20 /** 21 * 用二进制来表示这一段涂过的颜色, 22 * 1表示涂了的颜色,0表示没有涂的 23 * 颜色 。用第i位表示第i种颜色 24 */ 25 int painted; 26 int state; //延时标记,更新第i种颜色 27 int from; 28 int end; 29 TreeNode* left; 30 TreeNode* right; 31 TreeNode(){ init(); } 32 TreeNode(int from, int end){ 33 init(); 34 this->from = from; 35 this->end = end; 36 } 37 }TreeNode; 38 typedef class Tree{ 39 public: 40 TreeNode* root; 41 Tree():root(NULL){} 42 Tree(int size){ 43 root = build(root, 1, size); 44 } 45 void pushUp(TreeNode* node){ 46 node->painted = node->left->painted | node->right->painted; 47 } 48 void pushDown(TreeNode* node){ 49 50 node->left->state = node->state; 51 node->left->painted = 1 << (node->state - 1); 52 53 node->right->state = node->state; 54 node->right->painted = 1 << (node->state - 1); 55 56 node->state = 0; 57 58 } 59 TreeNode* build(TreeNode *root, int from, int end){ 60 root = new TreeNode(from, end); 61 if(from == end){ 62 root->painted = 0x01; 63 return root; 64 } 65 int mid = (from + end) >> 1; 66 root->left = build(root->left, from, mid); 67 root->right = build(root->right, mid + 1, end); 68 pushUp(root); 69 return root; 70 } 71 void update(TreeNode* now, int from, int end, int value){ 72 if( from <= now->from && end >= now->end ){ 73 now->state = value; 74 now->painted = 1 << (value - 1); 75 return ; 76 } 77 if(now->state != 0) pushDown(now); 78 int mid = (now->from + now->end) >> 1; 79 if(end <= mid) update(now->left, from, end, value); 80 else if(from > mid) update(now->right, from, end, value); 81 else{ 82 update(now->left, from, mid, value); 83 update(now->right, mid + 1, end, value); 84 } 85 pushUp(now); 86 } 87 int query(TreeNode* now, int from, int end){ 88 if( from <= now->from && end >= now->end ) return now->painted; 89 if(now->state != 0) pushDown(now); 90 int mid = (now->from + now->end) >> 1; 91 if(end <= mid) return query(now->left, from, end); 92 else if(from > mid) return query(now->right, from, end); 93 else{ 94 return query(now->left, from, mid) | query(now->right, mid + 1, end); 95 } 96 } 97 }Tree; 98 Tree board; 99 int len,color,n; 100 char ch; 101 int a,b,c; 102 void _swap(int& a,int& b){ 103 int t = a; 104 a = b; 105 b = t; 106 } 107 int getSum(int x){ 108 int result = 0; 109 x &= (1 << color) - 1; 110 while(x != 0){ 111 result++; 112 x -= x&(-x); 113 } 114 return result; 115 } 116 int main(){ 117 scanf("%d%d%d",&len,&color,&n); 118 board = Tree(len); 119 for(int i = 1;i <= n;i++){ 120 cin>>ch; 121 if(ch == ‘C‘){ 122 scanf("%d%d%d",&a,&b,&c); 123 board.update(board.root, a, b, c); 124 }else{ 125 scanf("%d%d",&a,&b); 126 if(a > b) _swap(a,b); 127 int x = board.query(board.root, a, b); 128 printf("%d\n",getSum(x)); 129 } 130 } 131 return 0; 132 }
标签:
原文地址:http://www.cnblogs.com/yyf0309/p/5667029.html