您的位置:首页 > 其它

POJ 2777 Count Color

2010-10-20 19:44 232 查看
很好的一道线段树的题,问你在区间[l,r]上共有几种颜色,由于颜色只有30种,故可以用二进制储存颜色,1表示颜色1,10表示颜色2,100表示颜色3……依次类推,二进制数位上有几个数字,就有几种颜色

当着色区间大于等于当前区间时,着色后就可以返回,不必继续对下面的小区间着色,因为一次只能着一个颜色,下面子区间的颜色肯定与父区间的相同,当下次访问该区间时,再更新子区间的颜色

还有要注意的就是 位运算优先级小于加法!!!

代码:

#include<iostream>
using namespace std;
struct node
{
int left;
int right;
int color;
}tree[510005];
int ans;
int single(int a)//判断是否为单色
{
if(a&(a-1))
return 0;
else
return 1;
}
void build(int num,int l,int r)
{
if(l==r)
{
tree[num].left=tree[num].right=l;
tree[num].color=1;
return;
}
tree[num].left=l;
tree[num].right=r;
int mid=(l+r)>>1;
build(num<<1,l,mid);
build((num<<1)+1,mid+1,r);
tree[num].color=1;
}
void update(int num,int l,int r,int c)
{
if(tree[num].left>=l&&tree[num].right<=r)//着色区间包含该区间,则不必再对下面的子区间着色
{
tree[num].color=c;
return;
}
if(single(tree[num].color))//如果该区间为单色,下面的子区间可能还没更新,必须更新,否则递归函数向上返回更新父区间信息时会出错
{
tree[num*2].color=tree[num*2+1].color=tree[num].color;
}
int mid=(tree[num].left+tree[num].right)>>1;
if(mid>=r)
{
update(num<<1,l,r,c);
}
else if(mid<l)
{
update((num<<1)+1,l,r,c);
}
else
{
update(num<<1,l,mid,c);
update((num<<1)+1,mid+1,r,c);
}
tree[num].color=(tree[num*2].color|tree[num*2+1].color);
}
void query(int num,int l,int r)
{
if(tree[num].left>=l&&tree[num].right<=r||single(tree[num].color))//如果不判断是否为单色,可能单色情况下子区间还没更新,去访问时出错
{
ans|=tree[num].color;
return;
}
/*if(single(tree[num].color))
{
tree[num*2].color=tree[num*2+1].color=tree[num].color;
}*/
int mid=(tree[num].left+tree[num].right)>>1;
if(mid>=r)
{
query(num<<1,l,r);
}
else if(mid<l)
{
query((num<<1)+1,l,r);
}
else
{
query(num<<1,l,mid);
query((num<<1)+1,mid+1,r);
}
}
void cal()
{
int p=ans;
ans=0;
while(p)
{
if(p%2)//判断二进制数位上有几个1
ans++;
p=p>>1;
}
}
int main()
{
int l,t,oper,i,j,n,a,b,c,temp;
char com;
scanf("%d%d%d",&l,&t,&oper);
build(1,1,l);
while(oper--)
{
scanf("%c",&com);
if(com==10)
{
oper++;
continue;
}
if(com=='C')
{
scanf("%d%d%d",&a,&b,&c);
if(a>b)
{
temp=a;
a=b;
b=temp;
}
update(1,a,b,1<<(c-1));
continue;
}
else if(com=='P')
{
scanf("%d%d",&a,&b);
if(a>b)
{
temp=a;
a=b;
b=temp;
}
ans=0;
query(1,a,b);
cal();
printf("%d/n",ans);
continue;
}
}
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: