Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 40234 | Accepted: 12141 |
Description
Input
Output
Sample Input
2 2 4 C 1 1 2 P 1 2 C 2 2 2 P 1 2
Sample Output
2 1
Source
首先这道题是区间颜色覆盖问题,很容易想到线段树。然后我们又发现颜色数≤30,所以这道题就可以和位运算集合到一起,这个思路很巧妙。
注意:A可能大于B,这时需要交换两个数。(我一开始没发现结果RE了......T T)
#include
#include
#include
#include
#include
#include
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define LL long long
#define MAXN 100005
#define pa pair
using namespace std;
int l,c,n,x,y,z;
char ch;
struct tree_type
{
int l,r,w,tag;
}t[MAXN*4];
int read()
{
int ret=0,flag=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') flag=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();}
return ret*flag;
}
void pushup(int k)
{
t[k].w=t[k<<1].w|t[k<<1|1].w;
}
void update(int k,int z)
{
t[k].tag=t[k].w=z;
}
void pushdown(int k)
{
if (t[k].tag==0) return;
update(k<<1,t[k].tag);
update(k<<1|1,t[k].tag);
t[k].tag=0;
}
void build(int k,int x,int y)
{
t[k].l=x;
t[k].r=y;
t[k].tag=0;
if (x==y) {t[k].w=1;return;}
int mid=(x+y)>>1;
build(k<<1,x,mid);
build(k<<1|1,mid+1,y);
pushup(k);
}
void cover(int k,int x,int y,int z)
{
if (t[k].l==x&&t[k].r==y) {update(k,z);return;}
pushdown(k);
int mid=(t[k].l+t[k].r)>>1;
if (mid>=y) cover(k<<1,x,y,z);
else if (mid+1<=x) cover(k<<1|1,x,y,z);
else cover(k<<1,x,mid,z),cover(k<<1|1,mid+1,y,z);
pushup(k);
}
int query(int k,int x,int y)
{
if (t[k].l==x&&t[k].r==y) return t[k].w;
pushdown(k);
int mid=(t[k].l+t[k].r)>>1;
if (mid>=y) return query(k<<1,x,y);
else if (mid+1<=x) return query(k<<1|1,x,y);
else return (query(k<<1,x,mid)|query(k<<1|1,mid+1,y));
}
int calc(int x)
{
int ans=0;
for(;x;x>>=1) ans+=x&1;
return ans;
}
int main()
{
l=read();c=read();n=read();
build(1,1,l);
F(i,1,n)
{
ch=getchar();while (ch!='C'&&ch!='P') ch=getchar();
x=read();y=read();
if (x>y) swap(y,x);
if (ch=='C') z=read(),cover(1,x,y,1<<(z-1));
else printf("%d\n",calc(query(1,x,y)));
}
return 0;
}