您的位置:首页 > 其它

POJ--2777--Count Color

2013-03-06 16:17 344 查看
题目大意:给出一条长为L 的木棍,每次更新一段区间的颜色,颜色范围【1-30】,询问区间内有多少种颜色?

成段更新的线段树,终于过去了,,,

最先开始我是这样定义线段树的结构体的

struct node
{
int l,r;
int color;   //保存区间被涂了的所有颜色信息
};
除了一个区间标记外只有一个颜色标记,用颜色是否等于0来代替lazy标记,但是最后发现这样是错滴,因为往下push的时候,会使得区间错乱。。。很坑爹的

还是这样吧

struct node
{
int l,r;
int color;   //保存区间被涂了的所有颜色信息
int lazy;    //标记
};


最后的代码,注意细节

#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 100005
#define lc(c) ((c)<<1)
#define rc(c) ((c)<<1|1)
using namespace std;
struct node
{
int l,r;
int color;   //保存区间被涂了的所有颜色信息
int lazy;    //标记
}p[maxn<<2];
int n,m,q;
void build(int c,int x,int y)
{
p[c].l=x;
p[c].r=y;
p[c].lazy=0;
p[c].color=1;
if(x==y)
return;
else
{

int m=(x+y)>>1;
build(lc(c),x,m);
build(rc(c),m+1,y);
}
}
void pushdown(int c)
{
if(p[c].l==p[c].r)return;		//放置数组越界
p[c].lazy=0;
p[lc(c)].color=p[rc(c)].color=p[c].color;
p[lc(c)].lazy=p[rc(c)].lazy=1;
}
void maintain(int c)
{
p[c].color=p[lc(c)].color|p[rc(c)].color;
}
void change(int c,int x,int y,int cl)
{
int l=p[c].l,r=p[c].r;
if(p[c].lazy)
pushdown(c);
if(l==x&&r==y)
{
p[c].color=1<<(cl-1);
p[c].lazy=1;
return;
}
int m=(l+r)>>1;
if(m>=y)change(lc(c),x,y,cl);
else if(m<x)change(rc(c),x,y,cl);
else
{
change(lc(c),x,m,cl);
change(rc(c),m+1,y,cl);
}
maintain(c);
}
int findans(int c,int x,int y)
{
int l=p[c].l,r=p[c].r;
if(p[c].lazy)pushdown(c);
if(l==x&&r==y)return p[c].color;
int m=(l+r)>>1;
if(m>=y)return findans(lc(c),x,y);
else if(m<x)return findans(rc(c),x,y);
else return findans(lc(c),x,m)|findans(rc(c),m+1,y);
}
void Query(int x,int y)
{
int ans=0,sum=findans(1,x,y);
while(sum)
{
ans+=(sum&1);
sum>>=1;
}
printf("%d\n",ans);
}
int main()
{
int x,y,cl;
char tp;
while(scanf("%d%d%d",&n,&q,&m)!=EOF)
{
build(1,1,n);
while(m--)
{
getchar();
scanf("%c",&tp);
//cout<<"tp=="<<tp<<endl;
scanf("%d%d",&x,&y);
if(x>y)
{
x+=y;
y=x-y;
x=x-y;
}
if(tp=='C')
{
scanf("%d",&cl);
change(1,x,y,cl);
}
else
{
Query(x,y);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: