题意:给一些线段区间染色,然后问你一段区间的不同颜色的个数
分析:因为颜色比较小 可以压缩为二进制表示
细节详见代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int maxn = 1e5 + 20;
struct InterxTree
{
int sum[maxn<<2],set[maxn<<2];
void build()
{
sum[1]=1,set[1]=1;
}
void pushDown(int rt)
{
sum[rt<<1]=sum[rt<<1|1]=1<<(set[rt]-1);
set[rt<<1]=set[rt<<1|1]=set[rt];
set[rt]=-1;
}
void maintain(int rt)
{
sum[rt]=sum[rt<<1]|sum[rt<<1|1];
}
void update(int L,int R,int v,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
set[rt]=v;
sum[rt]=1<<(v-1);
return ;
}
if(~set[rt])
pushDown(rt);
int mid=(l+r)>>1;
if(L<=mid) update(L,R,v,lson);
if(R>mid) update(L,R,v,rson);
maintain(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
return sum[rt];
}
if(~set[rt]) // 查询时候不用pushdown 减少时间浪费
{
return 1<<(set[rt] -1);
}
int mid=(l+r)>>1;
int ans = 0;
if(L<=mid) ans |=query(L,R,lson);
if(R>mid) ans |=query(L,R,rson);
return ans;
}
}tree;
int main()
{
// freopen("1.txt","r",stdin);
int l,t,o;
while(~scanf("%d %d %d",&l,&t,&o))
{
tree.build();
while(o--)
{
char d = getchar();
int a,b,c;
while(!isalpha(d)) d = getchar();
if(d=='C')
{
scanf("%d %d %d",&a,&b,&c);
if(b<a)
swap(a,b);
tree.update(a,b,c,1,l,1);
}
else
{
scanf("%d %d",&a,&b);
if(b<a)
swap(a,b);
printf("%d\n",__builtin_popcount(tree.query(a,b,1,l,1))); // 数1的个数
}
}
}
return 0;
}