当看到这道题A时,激动了好一会,这个题完全凭借自己写的,一点都没有参考别人的,而且是一次性通过,通过做这道题,让我看到了线段树是多么的强大!

我感觉这道题和hdu 上的1169 差不多,都是标记颜色,只不过最后求的不太一样,这道题目求的是从标号为a的球到标号为b的球中间共出现多少种颜色!

直接贴代码了,相信学过线段树的都应该可以看懂!

# include<stdio.h>
# include<string.h>
struct node{
	int left,right,mid,num;///如果num==-1,说明该节点以下,出现了至少两种颜色!如果为一个正数,则存的是颜色的类型!
}a[400001];
int visit[32];
void make(int ans1 ,int ans2,int step)
{
	a[step].left=ans1;
	a[step].right=ans2;
	a[step].mid=(ans1+ans2)/2;
	a[step].num=1;
	if(ans1==ans2) return;
	make(ans1,a[step].mid,2*step);
	make(a[step].mid+1,ans2,2*step+1);
}
void update(int ans1,int ans2,int c,int step)
{
	if(a[step].left==ans1 && a[step].right==ans2)  
	{
		a[step].num=c;
		return;
	}
	if(a[step].num==c) return;
	if(a[step].num!=-1)
	{
		a[2*step].num=a[step].num;
		a[2*step+1].num=a[step].num;
		a[step].num=-1;
	}
	if(ans1>a[step].mid) update(ans1,ans2,c,2*step+1);
	else if(ans2<=a[step].mid) update(ans1,ans2,c,2*step);
	else 
	{
		update(ans1,a[step].mid,c,2*step);
		update(a[step].mid+1,ans2,c,2*step+1);
	}
}
void query(int ans1,int ans2,int step)
{
	if(a[step].num!=-1) {visit[a[step].num]=1;return;}
	if(ans2<=a[step].mid) query(ans1,ans2,2*step);
	else if(ans1>a[step].mid) query(ans1,ans2,2*step+1);
	else
	{
		query(ans1,a[step].mid,2*step);
		query(a[step].mid+1,ans2,2*step+1);
	}
}
int main()
{
	int i,n,m,t,a,b,temp,c,count;
	char s[3];
	while(scanf("%d%d%d",&n,&t,&m)!=EOF)
	{
		make(1,n,1);
		while(m--)
		{
			scanf("%s%d%d",s,&a,&b);
			if(a>b)
			{
				temp=a;
				a=b;
				b=temp;
			}
			if(s[0]=='C')
			{
				scanf("%d",&c);
				update(a,b,c,1);
			}
			else
			{
				memset(visit,0,sizeof(visit));
				query(a,b,1);
				count=0;
				for(i=1;i<=30;i++)
					if(visit[i]==1) count++;
					printf("%d\n",count);
			}
		}
	}
	return 0;
}




posted on 2010-08-23 20:57  奋斗青春  阅读(1594)  评论(1编辑  收藏  举报