poj 2777 Count Color 线段树

本文介绍了一种使用线段树解决区间染色问题的方法,通过二进制表示区间内的颜色种类,支持区间染色及查询颜色种类总数的操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:poj 2777

        给定一段区间,对该区间进行染色,询问操作

  染色操作对特定的区间进行染色

  询问操作求对应区间中节点颜色的种类总数

  线段树操作,因为颜色种类总数一共就30种,因此可以在节点中用用二进制表示区间中有的颜色。

/******************************************************
 * File Name:   2777.cpp
 * Author:      kojimai
 * Creater Time:2014年08月30日 星期六 00时25分57秒
 ******************************************************/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
struct seg
{
	int l,r,c;//c用二进制来表示当前段中颜色的种类
	bool flag;//表示当前段被涂上同样的颜色
}node[500005];

void buildtree(int l,int r,int num)
{
	node[num].l=l;
	node[num].r=r;
	node[num].flag=true;
	node[num].c=1;
	if(l==r)
		return;
	int mid=(l+r)/2;
	buildtree(l,mid,num*2);
	buildtree(mid+1,r,num*2+1);
}

int Count(int x)
{
	int ret=0;
	while(x)
	{
		if(x%2==1)
			ret++;
		x/=2;
	}
	return ret;
}
void update(int l,int r,int c,int num)
{
	if(node[num].l>=l&&node[num].r<=r)
	{
		node[num].c=(1<<(c-1));
		node[num].flag=true;
		return;
	}
	if(node[num].flag)
	{
		node[num*2].flag=true;
		node[num*2+1].flag=true;
		node[num*2].c=node[num].c;
		node[num*2+1].c=node[num].c;
		node[num].flag=false;
	}
	int mid=(node[num].l+node[num].r)/2;
	if(mid>=r)
		update(l,r,c,num*2);
	else if(mid<l)
		update(l,r,c,num*2+1);
	else
	{
		update(l,mid,c,num*2);
		update(mid+1,r,c,num*2+1);
	}
	node[num].c=node[num*2].c|node[num*2+1].c;
	return;
}

int query(int l,int r,int num)
{
	//cout<<"l="<<l<<" r="<<r<<" nodel="<<node[num].l<<" noder="<<node[num].r<<" c="<<node[num].c<<endl;
	if(node[num].l==l&&node[num].r==r)
	{
		return node[num].c;
	}
	if(node[num].flag)
	{
		node[num*2].flag=node[num*2+1].flag=true;
		node[num*2].c=node[num].c;
		node[num*2+1].c=node[num].c;
		node[num].flag=false;
	}
	int mid=(node[num].l+node[num].r)/2;
	if(mid>=r)
		return query(l,r,num*2);
	else if(mid<l)
		return query(l,r,num*2+1);
	else
	{
		return query(l,mid,num*2)|query(mid+1,r,num*2+1);
	}
}

int main()
{
	int L,t,q;
	while(~scanf("%d%d%d",&L,&t,&q))
	{
		buildtree(1,L,1);
		char ch;
		int x,y,z;
		while(q--)
		{
			getchar();
			scanf("%c",&ch);
			//cout<<ch<<endl;
			if(ch=='C')
			{
				scanf("%d%d%d",&x,&y,&z);
				if(x>y)
					swap(x,y);
				update(x,y,z,1);
			}
			else
			{
				scanf("%d%d",&x,&y);
				if(x>y)
					swap(x,y);
				int sum=query(x,y,1);
				cout<<Count(sum)<<endl;
			}
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值