線段樹+狀壓 色板遊戲
阿新 • • 發佈:2018-11-08
題意:一個色板,一開始全為 號顏色,有兩種操作:第一種是將區間 全部變為 號顏色,第二種是詢問區間 一共有多少種顏色。顏色數量 。
考慮將每一種顏色進行狀壓, 即表示這個區間的顏色狀壓後的值,每次更新使用 更新 ,修改就是區間覆蓋, 也直接覆蓋即可。
#include<bits/stdc++.h>
using namespace std;
struct node
{
int l,r;
int sum,tag;
}tr[404000];
int l,t,o;
void build(int rt,int l,int r)
{
tr[rt].l=l;
tr[rt].r=r;
if(l==r)
{
tr[rt].sum=1;
return;
}
int mid=(l+r)/2;
build(rt*2,l,mid);
build(rt*2+1,mid+1,r);
tr[rt].sum=tr[rt*2].sum|tr[rt*2+1].sum;
}
void pushdown(int rt)
{
if(!tr[rt].tag)
return;
tr[rt*2].tag=tr[rt].tag;
tr[rt*2+1].tag=tr[rt].tag;
tr[rt*2].sum=tr[rt].tag;
tr[rt*2+1].sum=tr[rt].tag;
tr[rt].tag=0;
}
void update(int rt,int L,int R,int c)
{
int l=tr[rt].l;
int r=tr[rt].r;
if(l>=L&&r<=R)
{
tr[rt].sum=tr[rt].tag=c;
return;
}
pushdown(rt);
int mid=(l+r)/2;
if(L<=mid)
update(rt*2,L,R,c);
if(R>mid)
update(rt*2+1,L,R,c);
tr[rt].sum=tr[rt*2].sum|tr[rt*2+1].sum;
}
int query(int rt,int L,int R)
{
int l=tr[rt].l;
int r=tr[rt].r;
if(l>=L&&r<=R)
return tr[rt].sum;
pushdown(rt);
int mid=(l+r)/2,res=0;
if(L<=mid)
res|=query(rt*2,L,R);
if(R>mid)
res|=query(rt*2+1,L,R);
return res;
}
char s[100];
int main()
{
cin>>l>>t>>o;
build(1,1,100000);
for(int i=1;i<=o;++i)
{
scanf("%s",s+1);
if(s[1]=='C')
{
int L,R,d;
scanf("%d%d%d",&L,&R,&d);
if(L>R)
swap(L,R);
update(1,L,R,1<<(d-1));
}
if(s[1]=='P')
{
int L,R;
scanf("%d%d",&L,&R);
if(L>R)
swap(L,R);
int res=query(1,L,R),ans=0;
while(res)
{
ans+=res&1;
res/=2;
}
printf("%d\n",ans);
}
}
return 0;
}
/*
6 3 4
C 2 3 2
C 3 4 3
P 1 5
*/