线段树喜闻乐见的区间染色问题,一个主要的问题就是要询问一个区间内有多少种颜色,乍一看,其实不怎么好做,但是仔细一看,仅仅只有三十种颜色,果断的状态压缩走起,我们可以用1代表第一种颜色,2代表第二中颜色,4代表第三种颜色,8代表第四种颜色,以此类推,这样的话如果两个区间的颜色不一样,按位或一下就好说了。然后我们查询的时候只需要询问查询结果的二进制位里面有多少个1就行了。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
const int maxn = 111111;
int t, n, m, cnt;
int col[maxn << 2], cov[maxn << 2];
void PushDown(int rt){
if (cov[rt] != -1){
cov[rt << 1] = cov[rt << 1 | 1] = cov[rt];
col[rt << 1] = col[rt << 1 | 1] = cov[rt];
cov[rt] = -1;
}
}
void PushUp(int rt){
col[rt] = col[rt << 1] | col[rt << 1 | 1];
}
void build(int l, int r, int rt){
col[rt] = 1; cov[rt] = -1;
if (l == r) return;
int m = (l + r) >> 1;
build(lson); build(rson);
}
void update(int ll, int rr, int c, int l, int r, int rt){
if (ll <= l && rr >= r){
cov[rt] = col[rt] = (1 << (c - 1));
return;
}
PushDown(rt);
int m = (l + r) >> 1;
if (ll <= m) update(ll, rr, c, lson);
if (rr > m) update(ll, rr, c, rson);
PushUp(rt);
}
void query(int ll, int rr, int l, int r, int rt){
if (ll <= l && rr >= r){
cnt |= col[rt];
return;
}
PushDown(rt);
int m = (l + r) >> 1;
if (ll <= m) query(ll, rr, lson);
if (rr > m) query(ll, rr, rson);
}
int main(){
while(~scanf("%d%d%d", &n, &t, &m)){
build(1, n, 1);
while(m--){
char op[2];
int x, y, z;
scanf("%s", op);
if (op[0] == 'C'){
scanf("%d%d%d", &x, &y, &z);
if (x > y) swap(x, y);
update(x, y, z, 1, n, 1);
}
else{
scanf("%d%d", &x, &y);
cnt = 0;
if (x > y) swap(x, y);
query(x, y, 1, n, 1);
int ans = 0;
while(cnt){
ans += (cnt % 2);
cnt >>= 1;
}
printf("%d\n", ans);
}
}
}
return 0;
}