题目: 传送门
思路:
节点存的是[L,R]区间的颜色分部情况,我们可以用二进制来表示 颜色是否存在.
题目输入的l,r可能是相反的,这种情况我们要先交换一下它们的值(第二次刷还是被坑了…)
Ac_code
using namespace std;
const int maxn = 1e5+7;
int L,T,O;
int tr[maxn<<2];
int lazy[maxn<<2];
int clors[35];
void pushdown(int num) {
if(lazy[num] == 0) return ;
lazy[num<<1] = lazy[num<<1|1] = lazy[num];
tr[num<<1] = lazy[num];
tr[num<<1|1] = lazy[num];
lazy[num] = 0;
return ;
}
void build(int l,int r,int num) {
lazy[num] = 0;
if(l ==r) {
tr[num] = 1;
return ;
}
int mid =(l+r) >>1;
build(l,mid,num<<1);
build(mid+1,r,num<<1|1);
tr[num] = tr[num<<1] | tr[num<<1|1];
return ;
}
void modify(int l,int r,int num,int le,int ri,int cl) {
if(ri<l || r<le) return ;
if(le<=l&&r<=ri) {
lazy[num] = cl;
tr[num] = cl;
//cout<<l<<' '<<r<<' '<<num<<endl;
return ;
}
int mid = (l+r)>>1;
pushdown(num);
if(le<=mid) modify(l,mid,num<<1,le,ri,cl);
if(mid<ri) modify(mid+1,r,num<<1|1,le,ri,cl);
tr[num] = tr[num<<1] | tr[num<<1|1];
// cout<<tr[num]<<endl;
return ;
}
void quriy(int l,int r,int num,int le,int ri,int& ans) {
if(ri<l|| r<le ) return ;
if(le<=l&&r<=ri) {
ans |= tr[num];
return ;
}
int mid =(l+r) >>1;
pushdown(num);
if(le<=mid) quriy(l,mid,num<<1,le,ri,ans);
if(mid<ri) quriy(mid+1,r,num<<1|1,le,ri,ans);
tr[num] = tr[num<<1] | tr[num<<1|1];
return ;
}
int getsum(int ans) {
int sum = 0;
while(ans != 0) {
if(ans&1) sum++;
ans >>= 1;
}
return sum;
}
int main() {
clors[1] = 1;
scanf("%d%d%d",&L,&T,&O);
for(int i=2;i<=30;i++) clors[i] = clors[i-1]<<1;
build(1,L,1);
while(O--) {
char op;
int l,r,c;
scanf(" %c",&op);
if(op == 'C') {
scanf("%d%d%d",&l,&r,&c);
//cout<<clors[c] <<endl;
if(l>r) swap(l,r);
modify(1,L,1,l,r,clors[c]);
}
else {
scanf("%d%d",&l,&r);
int ans = 0;
if(l>r) swap(l,r);
quriy(1,L,1,l,r,ans);
printf("%d\n", getsum(ans));
}
}
return 0;
}