给一个固定长度为L的画板 最初的全部被初始化呢为1这个颜色
有两个操作:
C A B C:区间AB内涂上颜色C。
P A B:查询区间AB内颜色种类数。
思路:
因为颜色的数量十分的少,所以可以用二进制的状态1 用位运算来进行状态的转移
state=state1|state2
通过lazy数组进行操作
首先要理解pushdown,与maintain (pushup)的真正用意
首先此题会出现左边界大于右边界的情况
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
#define LL long long
#define bug puts("*********")
using namespace std;
const int N=102000;
int setv[N*4];
int cnt[N*4];
int state[N*4];
int len,t,o;
int Hash[N];
void PushDown(int ind){
if(setv[ind]!=-1){
setv[ind<<1]=setv[ind<<1|1]=setv[ind];
state[ind<<1]=state[ind<<1|1]=1<<(setv[ind]-1);
setv[ind]=-1;
}
}
void maintain(int ind){
state[ind]=state[ind<<1]|state[ind<<1|1];
}
void Update(int L,int R,int val,int sL,int sR,int ind){
if(sL<=L&&sR>=R){
setv[ind]=val;
state[ind]=1<<(val-1);
return ;
}
if(sL>R||sR<L) return ; ///也可以用if(sl<=mid) 。。。。if(sr>mid) 代替
PushDown(ind);
int mid=L+(R-L)/2;
Update(L,mid,val,sL,sR,ind<<1);
Update(mid+1,R,val,sL,sR,ind<<1|1);
maintain(ind);
}
int Query(int L,int R,int sl,int sr,int ind){
if(sl<=L&&sr>=R){
return state[ind];
}
if(sl>R||sr<L) return 0; ///无结束条件就会RE
PushDown(ind); ///必须有,此步是为了继续更新节点,存在Update()中更新的区间与Query()中询问的区间不同,
///然而在Update()中只要给区间的父节点赋完值就结束了,他们的子区间并没有被更新过。
///如果不加这一步的话,会出现子区间未被更新。
int mid=L+(R-L)/2;
return Query(L,mid,sl,sr,ind<<1)|Query(mid+1,R,sl,sr,ind<<1|1);
}
char s[3];
int u,v,d;
int main(){
//memset(setv,-1,sizeof(setv));
setv[1]=1; ///全体染色为1
scanf("%d%d%d",&len,&t,&o);
// for(int i=0;i<=len*4+100;i++){
// setv[i]=1;
// }
while(o--){
scanf("%s",s);
if(s[0]=='C'){
scanf("%d%d%d",&u,&v,&d);
if(u>v) swap(u,v);
Update(1,len,d,u,v,1);
}
else{
scanf("%d%d",&u,&v);
if(u>v) swap(u,v); ///会有u>v的情况
//memset(Hash,0,sizeof(Hash));
int tt=Query(1,len,u,v,1); ///二进制状态
int ans=0; ///统计1的个数
while(tt){
ans+=tt%2;
tt/=2;
}
printf("%d\n",ans);
}
}
return 0;
}