POJ 2777.Count Color-线段树(区间染色+区间查询颜色数量二进制状态压缩)-若干年之前的一道题目。。。

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 53312   Accepted: 16050

Description

Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem. 

There is a very long board with length L centimeter, L is a positive integer, so we can evenly divide the board into L segments, and they are labeled by 1, 2, ... L from left to right, each is 1 centimeter long. Now we have to color the board - one segment with only one color. We can do following two operations on the board: 

1. "C A B C" Color the board from segment A to segment B with color C. 
2. "P A B" Output the number of different colors painted between segment A and segment B (including). 

In our daily life, we have very few words to describe a color (red, green, blue, yellow…), so you may assume that the total number of different colors T is very small. To make it simple, we express the names of colors as color 1, color 2, ... color T. At the beginning, the board was painted in color 1. Now the rest of problem is left to your. 

Input

First line of input contains L (1 <= L <= 100000), T (1 <= T <= 30) and O (1 <= O <= 100000). Here O denotes the number of operations. Following O lines, each contains "C A B C" or "P A B" (here A, B, C are integers, and A may be larger than B) as an operation defined previously.

Output

Ouput results of the output operation in order, each line contains a number.

Sample Input

2 2 4
C 1 1 2
P 1 2
C 2 2 2
P 1 2

Sample Output

2
1

 

 

题意就是区间染色,然后查询区间颜色数量,不能直接线段树上更新值,会被覆盖掉,所以要用二进制状态压缩一下,学到了小技巧,用二进制进行状态压缩。

有关位运算的老是记不住,笨死了。。。

贴一下大佬的有关位运算的:

位运算总结(按位与,或,异或)

还有一篇有关二进制状态压缩的:

状态压缩 位运算

本篇博客完全就是为了备忘才水的。。。

我写的时候,初始化写挫了,查询的时候,ret应该初始化为0,我写的1。。。

运算规则:0|0=0;  0|1=1;  1|0=1;   1|1=1;

     即 :参加运算的两个对象只要有一个为1,其值为1。

代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<bitset>
  6 #include<cassert>
  7 #include<cctype>
  8 #include<cmath>
  9 #include<cstdlib>
 10 #include<ctime>
 11 #include<deque>
 12 #include<iomanip>
 13 #include<list>
 14 #include<map>
 15 #include<queue>
 16 #include<set>
 17 #include<stack>
 18 #include<vector>
 19 using namespace std;
 20 typedef long long ll;
 21 typedef long double ld;
 22 typedef pair<int,int> pii;
 23 
 24 const double PI=acos(-1.0);
 25 const double eps=1e-6;
 26 const ll mod=1e9+7;
 27 const int inf=0x3f3f3f3f;
 28 const int maxn=1e5+10;
 29 const int maxm=100+10;
 30 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
 31 #define lson l,m,rt<<1
 32 #define rson m+1,r,rt<<1|1
 33 
 34 int tree[maxn<<2],lazy[maxn<<2];
 35 
 36 void pushup(int rt)
 37 {
 38     tree[rt]=tree[rt<<1]|tree[rt<<1|1];//颜色汇总
 39 }
 40 
 41 void pushdown(int rt)
 42 {
 43     if(lazy[rt]){
 44         lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
 45         tree[rt<<1]=tree[rt<<1|1]=lazy[rt];
 46         lazy[rt]=0;
 47     }
 48 }
 49 
 50 void build(int l,int r,int rt)
 51 {
 52     lazy[rt]=0;
 53     tree[rt]=1;
 54     if(l==r){
 55         return ;
 56     }
 57 
 58     int m=(l+r)>>1;
 59     build(lson);
 60     build(rson);
 61     pushup(rt);
 62 }
 63 
 64 void update(int L,int R,int c,int l,int r,int rt)
 65 {
 66     if(r<L||l>R) return ;
 67     if(L<=l&&r<=R){
 68         lazy[rt]=1<<(c-1);//二进制状态压缩保存颜色
 69         tree[rt]=1<<(c-1);
 70         return ;
 71     }
 72 
 73     pushdown(rt);
 74     int m=(l+r)>>1;
 75     if(L<=m) update(L,R,c,lson);
 76     if(R> m) update(L,R,c,rson);
 77     pushup(rt);
 78 }
 79 
 80 int query(int L,int R,int l,int r,int rt)
 81 {
 82     if(r<L||l>R) return 0;
 83     if(L<=l&&r<=R){
 84         return tree[rt];
 85     }
 86 
 87     pushdown(rt);
 88     int m=(l+r)>>1;
 89     int ret=0;
 90     if(L<=m) ret|=query(L,R,lson);
 91     if(R> m) ret|=query(L,R,rson);
 92     return ret;
 93 }
 94 
 95 int main()
 96 {
 97     ios;
 98     int n,m,q;
 99     cin>>n>>m>>q;
100     build(1,n,1);
101     while(q--){
102         char op[2];
103         int l,r,color;
104         cin>>op;
105         if(op[0]=='C'){
106             cin>>l>>r>>color;
107             if(l>r) swap(l,r);
108             update(l,r,color,1,n,1);
109         }
110         else{
111             cin>>l>>r;
112             if(l>r) swap(l,r);
113             int cnt=query(l,r,1,n,1);
114             int ans=0;
115             while(cnt){
116                 if(cnt&1) ans++;
117                 cnt>>=1;
118             }
119             cout<<ans<<endl;
120         }
121     }
122     return 0;
123 }

。。。


原文地址:https://www.cnblogs.com/ZERO-/p/10431873.html