題目大意
描述
給一塊長爲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;
}