您的位置:首页 > 其它

poj 2777 Count Color(线段树区间更新)

2013-06-17 16:04 274 查看
题目:http://poj.org/problem?id=2777

大意: 有个L长得木板, T种颜色,O个操作,分两种操作,一种是给从a到b区间染颜色c,另一种是询问区间a到b有多少种不同的颜色。

思路:线段树区间更新的题目,基本是模板题;

   注意:由于颜色的种类很少,所以可以用位操作来表示颜色;一个整数可以表示一段的颜色状态。

代码:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1000000;
int tree[maxn*4];//存储区间内有多少种颜色
int lz[maxn*4];//延迟标记数组
int color;
void push(int w)
{
tree[w]=tree[w<<1]|tree[w<<1|1];
}
void build(int l,int r,int w)
{
if(l==r)
{
tree[w]=1;
return ;
}
int m=(l+r)>>1;
build(l,m,w<<1);
build(m+1,r,w<<1|1);
push(w);
}
void update(int L,int R,int x,int l,int r,int w)
{
if(L<=l&&R>=r)
{
lz[w]=w;//标记延迟
tree[w]=1<<(x-1);
return ;
}
if(lz[w]!=0)//消除延迟标记
{
lz[w*2]=lz[w*2+1]=lz[w];
tree[w<<1]=tree[w<<1|1]=tree[w];
lz[w]=0;
}
int m=(l+r)>>1;
if(L>m)
update(L,R,x,m+1,r,w<<1|1);
else if(R<=m)
update(L,R,x,l,m,w<<1);
else
{
update(L,m,x,l,m,w<<1);
update(m+1,R,x,m+1,r,w<<1|1);
}
push(w);//更新
}
void query(int L,int R,int l,int r,int w)
{
if((L<=l&&R>=r)||lz[w]!=0)//如果这个区间有延迟标记,则表示这个区间内是一种颜色,不需要再访问其儿子
{
color|=tree[w];//用位操作存储颜色
return;
}
int m=(l+r)>>1;
if(R<=m)
{
query(L,R,l,m,w<<1);
}
else if(L>m)
{
query(L,R,m+1,r,w<<1|1);
}
else
{
query(L,m,l,m,w<<1);
query(m+1,R,m+1,r,w<<1|1);
}
}
int main()
{
int L,T,O;
while(scanf("%d%d%d",&L,&T,&O)!=EOF)
{
int i;
char ch;
int a,b,c;
int chan;
memset(lz,0,sizeof(lz));
build(1,L,1);
for(i=0; i<O; i++)
{
getchar();
scanf("%c",&ch);
scanf("%d%d",&a,&b);
if(a>b)
{
chan=a;
a=b;
b=chan;
}
if(ch=='C')
{
scanf("%d",&c);
update(a,b,c,1,L,1);
}
else
{
color=0;
query(a,b,1,L,1);
int sum=0;
for(int j=0; j<T; j++)
{
if(color&(1<<j))//计算二进制中1的个数,代表颜色的种数
{
sum++;
}
}
printf("%d\n",sum);
}
}
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: