luogu 1558 色板游戏
题目背景
阿宝上学了,今天老师拿来了一块很长的涂色板。
题目描述
色板长度为L,L是一个正整数,所以我们可以均匀地将它划分成L块1厘米长的小方格。并从左到右标记为1, 2, ... L。
现在色板上只有一个颜色,老师告诉阿宝在色板上只能做两件事:
- "C A B C" 指在A到 B 号方格中涂上颜色 C。
- "P A B" 指老师的提问:A到 B号方格中有几种颜色。
学校的颜料盒中一共有 T 种颜料。为简便起见,我们把他们标记为 1, 2, ... T. 开始时色板上原有的颜色就为1号色。 面对如此复杂的问题,阿宝向你求助,你能帮助他吗?
输入格式
第一行有3个整数 L (1 <= L <= 100000), T (1 <= T <= 30) 和 O (1 <= O <= 100000)。 在这里O表示事件数。
接下来 O 行, 每行以 "C A B C" 或 "P A B" 得形式表示所要做的事情(这里 A, B, C 为整数, 可能A> B,这样的话需要你交换A和B)
输出格式
对于老师的提问,做出相应的回答。每行一个整数。
输入输出样例
输入 #1
2 2 4 C 1 1 2 P 1 2 C 2 2 2 P 1 2
输出 #1
2 1
分析
涂色的题,可以用状态压缩来存颜色的状态。
用一个数组存是否是单一颜色,如果儿子节点不是单一颜色或两个区间颜色不一样,那么就不是单一颜色
若是单一颜色的区间,在遍历时要下放
代码
1 /*********************** 2 User:Mandy.H.Y 3 Language:c++ 4 Problem: 5 Algorithm: 6 ***********************/ 7 8 #include<bits/stdc++.h> 9 #define lson l,mid,k<<1 10 #define rson mid + 1,r,k<<1|1 11 12 using namespace std; 13 14 const int maxn = 1e5 + 5; 15 16 int n,t,o,ans; 17 bool tree[maxn << 2]; 18 int colo[maxn << 2]; 19 20 template<class T>inline void read(T &x){ 21 x = 0;bool flag = 0;char ch = getchar(); 22 while(!isdigit(ch)) flag |= ch == '-',ch = getchar(); 23 while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch^ 48),ch = getchar(); 24 if(flag) x = -x; 25 } 26 27 template<class T>void putch(const T x){ 28 if(x > 9) putch(x / 10); 29 putchar(x % 10 | 48); 30 } 31 32 template<class T>void put(const T x){ 33 if(x < 0) putchar('-'),putch(-x); 34 else putch(x); 35 } 36 37 void file(){ 38 freopen("testdata(2).in","r",stdin); 39 freopen("1558.out","w",stdout); 40 } 41 42 void buildtree(int l,int r,int k){ 43 tree[k] = 1;colo[k] = 2; 44 if(l == r) return; 45 int mid = (l + r) >> 1; 46 buildtree(lson); 47 buildtree(rson); 48 } 49 50 void readdata(){ 51 read(n);read(t);read(o); 52 buildtree(1,n,1); 53 } 54 55 void pushdown(int k){ 56 if(tree[k] == 1){ 57 tree[k<<1] = 1; 58 tree[k<<1|1] = 1; 59 colo[k<<1] = colo[k]; 60 colo[k<<1|1] = colo[k]; 61 } 62 } 63 64 void modify(int l,int r,int k,int x,int y,int color){ 65 if(x <= l && r <= y){ 66 tree[k] = 1;//tree用于标记是否为单一色彩 67 colo[k] = (1 << color); 68 return; 69 } 70 int mid = (l + r) >> 1; 71 pushdown(k);//%%% 72 if(x <= mid) modify(lson,x,y,color); 73 if(y > mid) modify(rson,x,y,color); 74 colo[k] = colo[k<<1] | colo[k<<1|1];//状态压缩存颜色 75 if((colo[k<<1] != colo[k<<1|1]) || (tree[k<<1] == 0) || (tree[k<<1|1] == 0)) tree[k] = 0; 76 //%%% 注意 三个条件 77 } 78 79 void query(int l,int r,int k,int x,int y){ 80 if(x <= l && r <= y){ 81 ans |= colo[k]; 82 return; 83 } 84 pushdown(k);//%%% 85 int mid = (l + r) >> 1; 86 if(x <= mid) query(lson,x,y); 87 if(y > mid) query(rson,x,y); 88 } 89 90 void work(){ 91 while(o--){ 92 char c = getchar(); 93 int l,r,x; 94 while(c != 'C' && c != 'P') c = getchar(); 95 if(c == 'C') { 96 read(l);read(r);read(x); 97 if(l > r) swap(l,r); 98 modify(1,n,1,l,r,x); 99 } else { 100 read(l);read(r); 101 if(l > r) swap(l,r); 102 ans = 0; 103 int num = 0; 104 query(1,n,1,l,r); 105 for(int i = ans;i;i -= (i & (-i))) ++num;//%%% 106 put(num); 107 putchar('\n'); 108 } 109 } 110 } 111 112 int main(){ 113 // file(); 114 readdata(); 115 work(); 116 return 0; 117 }
非做顽石不可,哪管他敬仰暗唾