题解 P1558 【色板游戏】
看大佬们高级的数据结构,似乎对于本蒟蒻来说有些难懂;
我来给初学者们介绍一下STL的bitset。
首先,需要<bitset>头文件。
#include<bitset>
using namespace std;
bitset相当于一个bool数组,但是优点是两个bitset之间可以进行按位运算。
定义方式如下:
bitset<1000>a
初始值是全部设为 0 的。
或者
string s="1010101"
bitset <1000>a1(s);
前面不足位用 0 补足;若字符串长度长于定义长度,只取前面部分。
之后就可以把它当做一个二进制数,进行与、或、非、异或、左右移运算了。
bitset<4> foo (string("1001"));
bitset<4> bar (string("0011"));
foo^=bar; //1010(foo对bar按位异或后赋值给foo)
foo&=bar; //0010(按位与后赋值给foo)
foo|=bar; //0011(按位或后赋值给foo)
foo<<=2; //1100(左移2位,低位补0,有自身赋值)
foo>>=1; //0110(右移1位,高位补0,有自身赋值)
另外他还可以实现其他的一些功能。
a.set() //将所有位变成1
a.set(k) //将第k位变成1,超限会报错
a.reset() //清空bitset
a.reset(k) //把第k位变成0
a.flip() //将所有位按位取反
a.flip(k) //将第k位按位取反
a.count() //返回bitset中1的个数
a.all() //若bitset内全是1返回1,否则返回0
比如本题,正好可以利用或的性质:两个数中只要有一个该位上是1,结果的这位上就是1。
详见代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<bitset>
using namespace std;
int X,W;char ch;
inline int read()
{
X=0,W=1;ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')W=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){X=(X<<1)+(X<<3)+ch-48;ch=getchar();}
return X*W;
}
struct tree{
int l;
int r;
int lazy;
bitset<30>p;
}tr[400001];
bitset<30>ans;
int a[100001];
void pushdown(int k)
{
if(tr[k].lazy==0)return;
tr[k<<1].lazy=tr[k].lazy;
tr[k<<1].p.reset();
tr[k<<1].p.set(tr[k].lazy,1);
tr[k<<1|1].lazy=tr[k].lazy;
tr[k<<1|1].p.reset();
tr[k<<1|1].p.set(tr[k].lazy,1);
tr[k].lazy=0;
}
void build(int k)
{
tr[k].p.set(1,1);
if(tr[k].l==tr[k].r)return;
int mid=(tr[k].l+tr[k].r)>>1;
tr[k<<1].l=tr[k].l;
tr[k<<1].r=mid;
tr[k<<1|1].l=mid+1;
tr[k<<1|1].r=tr[k].r;
build(k<<1),build(k<<1|1);
}
void change(int k,int l,int r,int c)
{
if(tr[k].l==l&&tr[k].r==r){
tr[k].lazy=c;
tr[k].p.reset();
tr[k].p.set(c,1);
return;
}
pushdown(k);
if(l>tr[k<<1].r)change(k<<1|1,l,r,c);
else if(r<tr[k<<1|1].l)change(k<<1,l,r,c);
else change(k<<1,l,tr[k<<1].r,c),change(k<<1|1,tr[k<<1|1].l,r,c);
tr[k].p=(tr[k<<1].p|tr[k<<1|1].p);
}
void ask(int k,int l,int r)
{
if(tr[k].l==l&&tr[k].r==r){
ans|=tr[k].p;
return;
}
pushdown(k);
if(l>tr[k<<1].r)ask(k<<1|1,l,r);
else if(tr[k<<1|1].l>r)ask(k<<1,l,r);
else ask(k<<1,l,tr[k<<1].r),ask(k<<1|1,tr[k<<1|1].l,r);
}
int main()
{
int n=read(),t=read(),m=read();
tr[1].l=1,tr[1].r=n;
build(1);
char op;int u,v,w;
while(m--){
scanf(" %c",&op);
u=read(),v=read();
if(u>v)swap(u,v);
switch(op){
case 'C':{
w=read();
change(1,u,v,w);
break;
}
case 'P':{
ask(1,u,v);
printf("%d\n",ans.count());
ans.reset();
break;
}
}
}
return 0;
}