您的位置:首页 > 其它

POJ 2777 Count Color 线段树 成段更新

2013-03-06 21:03 232 查看
题意:经过一系列操作之后,求可以看见的颜色数

做法:一开始2了用了个数组简单统计了一下,果断TLE,所以后来只能想个法子,用节点记录区间中还有颜色的种类,用二进制数压缩即可

#include<cstdio>
#include<cstring>
#define left l,m,x<<1
#define right m+1,r,x<<1|1
const int LMT=100003;
int colo[LMT<<2],ans,L,T;
bool cov[LMT<<2],vis[35];
//扳子和段的区别啊
void cut(int x)
{
	if(cov[x])
	{
	    cov[x<<1]=cov[x<<1|1]=cov[x];
	    colo[x<<1]=colo[x<<1|1]=colo[x];
	    cov[x]=0;
	}
}
void update(int co,int L,int R,int l,int r,int x)
{
	if(L<=l&&r<=R)
	{
		colo[x]=1<<co;
		cov[x]=1;
		return;
	}
	cut(x);
	int m=(l+r)>>1;
	if(L<=m)update(co,L,R,left);
	if(R>m)update(co,L,R,right);
	colo[x]=colo[x<<1]|colo[x<<1|1];
}
void query(int L,int R,int l,int r,int x)
{
	if(L<=l&&r<=R)
	{
	    for(int i=0;i<T;i++)
	    if(1<<i&colo[x]&&vis[i]==0)
	    {
	        vis[i]=1;
	        ans++;
	    }
		return ;
	}
	if(l==r)return;
	cut(x);
	int m=(l+r)>>1;
	if(L<=m)query(L,R,left);
	if(R>m)query(L,R,right);
}
int main(void)
{
	int O,l,r,d;
	char op;
	scanf("%d%d%d",&L,&T,&O);
	colo[1]=1;
	cov[1]=1;
	while(O--)
	{
	    op=getchar();
	    while(op!='C'&&op!='P')op=getchar();
		if(op=='C')
		{
			scanf("%d%d%d",&l,&r,&d);
			d--;
			if(l>r)
			{
			    int t=l;
			    l=r;r=t;
			}
			update(d,l,r,1,L,1);
		}
		else
		{
			scanf("%d%d",&l,&r);
					if(l>r)
			{
			    int t=l;
			    l=r;r=t;
			}
			memset(vis,0,sizeof(vis));
			ans=0;
			query(l,r,1,L,1);
			printf("%d\n",ans);
		}
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: