题目大意:
C a b 在AB之间涂上同一个颜色。
Q a b 输出AB之间有多少种不同的颜色。
思路:
一开始没有意识到是输出不同的颜色的数量。而不是有多少段与相邻不一样的区间。
后来在网上看到说用位运算。
然后才知道。
其实是在树上用一个数记录这个区间涂了哪几种颜色。然后与下一个用或运算上推。
#include <iostream>
#include <cstdio>
#include <algorithm>
#define MAXN 200005
using namespace std;
int tree[MAXN<<2];
int vis[MAXN<<2];
void pushup(int num)//向上推,用或可以记录两边记录的颜色
{
tree[num] = (tree[num<<1] | tree[num<<1|1]);
}
void pushdown(int num)
{
if(vis[num]!=0)
{
tree[num<<1]=tree[num<<1|1]=tree[num];
vis[num<<1]=vis[num<<1|1]=vis[num];
vis[num]=0;
}
}
void build(int num,int l,int r)
{
vis[num]=0;
tree[num]=1;
if(l==r)return;
int mid=(l+r)>>1;
build(num<<1,l,mid);
build(num<<1|1,mid+1,r);
pushup(num);
}
void update(int num,int s,int e,int l,int r,int val)
{
int mid=(s+e)>>1;
if(l<=s && r>=e)
{
vis[num]=1;
tree[num] = val;
return;
}
pushdown(num);
if(l<=mid)update(num<<1,s,mid,l,r,val);
if(r>mid)update(num<<1|1,mid+1,e,l,r,val);
pushup(num);
}
int query(int num,int s,int e,int l,int r)
{
int mid=(s+e)>>1;
if(s==l && e==r)
return tree[num];
pushdown(num);
if(r<=mid)return query(num<<1,s,mid,l,r);
else if(l>mid)return query(num<<1|1,mid+1,e,l,r);
else
return (query(num<<1,s,mid,l,mid) | query(num<<1|1,mid+1,e,mid+1,r));
}
int main()
{
int n,m,t;
while(scanf("%d%d%d",&n,&t,&m)!=EOF)
{
build(1,1,n);
char op[5];
for(int i=1;i<=m;i++){
scanf("%s",op);
if(op[0]=='C')
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
update(1,1,n,a,b,1<<(c-1));
}
else
{
int a,b;
scanf("%d%d",&a,&b);
if(a>b)swap(a,b);//注意题目中说 A可能大于B。。。在这里跪了好多次
int p = query(1,1,n,a,b);
int ans=0;
while(p)
{
if(p%2!=0)
ans++;
p=(p>>1);
}
printf("%d\n",ans);
}
}
}
return 0;
}