luogu 1558 色板游戏

题目背景

阿宝上学了,今天老师拿来了一块很长的涂色板。

题目描述

色板长度为L,L是一个正整数,所以我们可以均匀地将它划分成L块1厘米长的小方格。并从左到右标记为1, 2, ... L。

现在色板上只有一个颜色,老师告诉阿宝在色板上只能做两件事:

  1. "C A B C" 指在A到 B 号方格中涂上颜色 C。
  2. "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('
');
108         }
109     }
110 }
111 
112 int main(){
113 //    file();
114     readdata();
115     work();
116     return 0; 
117 }
View Code
非做顽石不可,哪管他敬仰暗唾
原文地址:https://www.cnblogs.com/Mandy-H-Y/p/11421149.html