色板長度爲 , 是一個正整數,所以我們可以均勻地將它劃分成 塊 釐米長的小方格。並從左到右標記爲 。
現在色板上只有一個顏色,老師告訴阿寶在色板上只能做兩件事:
“C A B C” 指在 到 號方格中塗上顏色
C
。“P A B” 指老師的提問: 到 號方格中有幾種顏色。
學校的顏料盒中一共有 種顏料。爲簡便起見,我們把他們標記爲 . 開始時色板上原有的顏色就爲 號色。 面對如此複雜的問題,阿寶向你求助,你能幫助他嗎?
這道題目,我們發現 , 的值非常小。
考慮建 棵線段樹,每顆線段樹維護是否有這種顏色,需要區間全部清零和區間全部賦值。
我使用的是封裝數據結構,註釋寫的很清楚了
#include <bits/stdc++.h>
#define ls num<<1
#define rs num<<1|1
using namespace std;
typedef long long ll;
template<typename T>inline void read(T &FF){
T RR=1;FF=0;char CH=getchar();
for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
FF*=RR;
}
const int MAXN=1e5+10;
int a[MAXN];
struct Line_Tree{
struct Tree{
int l,r,lazy;//lazy:1爲區間賦值,2爲區間清零
bool f;
}t[MAXN<<2];
void pushup(int num){
t[num].f=(t[ls].f||t[rs].f);//只要有一個部分有這種顏色,就說明這個區間有這種顏色。
}
void pushdown(int num){
if(t[num].lazy){
t[ls].lazy=t[rs].lazy=t[num].lazy;//lazy的傳遞,由於是區間覆蓋,所以直接賦值
t[ls].f=t[rs].f=(t[num].lazy==1);//1爲區間賦值,2爲區間清零
t[num].lazy=0;
}
}
void build(int num,int l,int r,int x){
t[num].l=l;t[num].r=r;t[num].lazy=false;
if(l==r){
t[num].f=(a[l]==x);//顯然QAQ
return;//直接return
}int mid=(l+r)>>1;
build(ls,l,mid,x);
build(rs,mid+1,r,x);
pushup(num);//注意pushup
}
void change1(int num,int l,int r){
if(t[num].l>=l&&t[num].r<=r){
t[num].lazy=1;//打標記
t[num].f=true;//直接操作
return;//直接return
}pushdown(num);//注意標記下傳
if(t[ls].r>=l)change1(ls,l,r);
if(t[rs].l<=r)change1(rs,l,r);
pushup(num);//注意pushup
}
void change2(int num,int l,int r){
if(t[num].l>=l&&t[num].r<=r){
t[num].lazy=2;//打標記
t[num].f=false;//直接操作
return;//直接return
}pushdown(num);//注意標記下傳
if(t[ls].r>=l)change2(ls,l,r);
if(t[rs].l<=r)change2(rs,l,r);
pushup(num);//注意pushup
}
bool query(int num,int l,int r){
if(t[num].l>=l&&t[num].r<=r)return t[num].f;//直接看
pushdown(num);//注意標記下傳
if(t[ls].r<l)return query(rs,l,r);
if(t[rs].l>r)return query(ls,l,r);
return (query(ls,l,r)||query(rs,l,r));//只要有一個是就是了
}
}T[32];//線段樹
int main(){
int n,t,E;read(n);read(t);read(E);
for(int i=1;i<=n;i++)a[i]=1;//初始化
for(int i=1;i<=t;i++)T[i].build(1,1,n,i);//初始化
while(E--){
char f=getchar();int a,b,c;
for(;f!='C'&&f!='P';)f=getchar();
read(a);read(b);if(a>b)swap(a,b);
if(f=='C'){
read(c);
for(int i=1;i<=t;i++)//枚舉顏色
if(i==c)T[i].change1(1,a,b);//區間賦值
else T[i].change2(1,a,b);//區間清零
}else{
int s=0;//計數器
for(int i=1;i<=t;i++)//枚舉顏色
if(T[i].query(1,a,b))s++;//如果有這種顏色
printf("%d\n",s);//輸出
}
}
return 0;
}