用线段树维护的差分序列,每次修改l加上首项,r+1减去末项,l+1到r加公差,91pts
2(P1558)
cnt中,每种颜色对应到一个位上,然后更新大区间的时候就把两个子区间按位或一下,最后数1的个数就能数出有多少种颜色,但是为什么只过了subtask1(((
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAXL=1e5+5;
struct SegmentTree{
ll l,r,cnt,tag;
#define l(x) T[x].l
#define r(x) T[x].r
#define cnt(x) T[x].cnt
#define tag(x) T[x].tag
}T[MAXL*4];
ll l,t,o;
ll countone(ll p){
ll cnt=0;
while(p){
if(p%2==1) cnt++;
p/=2;
}
return cnt;
}
void build(ll p,ll l,ll r){
l(p)=l,r(p)=r;
if(l==r){cnt(p)=1;return;}
ll mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
cnt(p)=cnt(p*2)|cnt(p*2+1);
}
void spread(ll p){
if(tag(p)){
cnt(p*2)=tag(p);
cnt(p*2+1)=tag(p);
tag(p*2)=tag(p);
tag(p*2+1)=tag(p);
tag(p)=0;
}
}
void change(ll p,ll l,ll r,ll d){
if(l<=l(p)&&r>=r(p)){
cnt(p)=1<<(d-1);
tag(p)=1<<(d-1);
return;
}
spread(p);
ll mid=(l(p)+r(p))/2;
if(l<=mid) change(p*2,l,r,d);
if(r>mid) change(p*2+1,l,r,d);
cnt(p)=cnt(p*2)|cnt(p*2+1);
}
ll ask(ll p,ll l,ll r){
if(l<=l(p)&&r>=r(p)) return cnt(p);
spread(p);
ll mid=(l(p)+r(p))/2,val=0;
if(l<=mid) val|=ask(p*2,l,r);
if(r>mid) val|=ask(p*2+1,l,r);
return val;
}
int main(){
cin>>l>>t>>o;
build(1,1,l);
for(int i=1;i<=o;i++){
char opt;
cin>>opt;
if(opt=='C'){
int a,b,c;
cin>>a>>b>>c;
change(1,a,b,c);
}
else if(opt=='P'){
int a,b;
cin>>a>>b;
cout<<countone(ask(1,a,b))<<endl;
}
}
return 0;
}