题目大意
描述
给一块长为L的长板染色,有两种操作:
1.“C A B C”用颜色C将板从A段着色到B段。
2.“P A B”输出A段和B段(包括A和B)之间的不同颜色的数量。
输入
第一行输入包含L(1 <= L <= 100000),T(1 <= T <= 30)和O(1 <= 0 <= 100000)。这里O表示操作次数。后O行,每行包含“C A B C”或“P A B”(这里A,B,C是整数,并且A可以大于B)。
输出
按顺序输出“P”操作结果,每行包含一个数字。
样例输入
2 2 4
C 1 1 2
P 1 2
C 2 2 2
P 1 2
样例输出
2
1
解题思路
用线段树维护染色操作。
线段树每个节点维护两个值,colo和lazy。colo表示此节点表示区间的颜色集合(二进制状压),lazy为区间覆盖标记。
pushup时,当前结点的colo即左右儿子的colo相或的值。
复杂度 O(nlogn)
Code
#include<cstdio>
#define lid id<<1
#define rid id<<1|1
#define mid ((tr[id].l+tr[id].r)>>1)
using namespace std;
inline int read(){
int x = 0;
bool fl = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if(ch == '-') fl = 0;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x << 1) + (x << 3) + ch - '0';
ch = getchar();
}
return fl ? x : -x;
}
const int N = 100005;
int n, t, q, a, b, c, ans;
char opt[2];
inline int lowbit(int x){ return x & -x; }
inline int countOne(int x){
int cnt = 0;
while(x){
cnt++;
x -= lowbit(x);
}
return cnt;
}
struct seg_tree{
int l, r, colo;
bool lazy;
}tr[N<<2];
void pushup(int id){
tr[id].colo = tr[lid].colo | tr[rid].colo;
}
void pushdown(int id){
if(tr[id].l != tr[id].r && tr[id].lazy){
tr[lid].colo = tr[rid].colo = tr[id].colo;
tr[lid].lazy = tr[rid].lazy = 1;
tr[id].lazy = 0;
}
}
void build(int id, int l, int r){
tr[id].l = l, tr[id].r = r;
tr[id].colo = (1 << 1);
tr[id].lazy = 1;
if(tr[id].l == tr[id].r) return;
build(lid, l, mid);
build(rid, mid+1, r);
pushup(id);
}
void modify(int id, int l, int r, int c){
pushdown(id);
if(tr[id].l == l && tr[id].r == r){
tr[id].colo = (1 << c);
tr[id].lazy = 1;
return;
}
if(r <= mid) modify(lid, l, r, c);
else if(l > mid) modify(rid, l, r, c);
else modify(lid, l, mid, c), modify(rid, mid+1, r, c);
pushup(id);
}
void query(int id, int l, int r){
pushdown(id);
if(tr[id].l == l && tr[id].r == r){
ans |= tr[id].colo;
return;
}
if(r <= mid) query(lid, l, r);
else if(l > mid) query(rid, l, r);
else query(lid, l, mid), query(rid, mid+1, r);
}
int main(){
n = read(), t = read(), q = read();
build(1, 1, n);
while(q--){
scanf("%s", opt);
a = read(), b = read();
if(a > b) a ^= b, b ^= a, a ^= b;
if(opt[0] == 'C'){
c = read();
modify(1, a, b, c);
}
else if(opt[0] == 'P'){
ans = 0;
query(1, a, b);
printf("%d\n", countOne(ans));
}
}
return 0;
}