hdu 2777(线段树)

这道题是看了别人的思路才做出来的。

刚看完这道题没什么思路,线段的长度是10^5,操作指令数是10^5,还要记录不同颜色种类数,觉着怎么写肯定都是要超时。我当时在节点里增加了一个数组记录已经出现的颜色数,硬着头皮写了一个代码,提交后无悬念TLE。后来又想着单纯的做一个延迟标记,让更新的节点效率达到最高,访问的话直接在一次访问中访问所有的叶节点,这样的话相当于增加了查询的消耗,降低了更新的消耗。想了想,觉得这样虽然能提高不少效率,但是离能过还有段儿距离。

我去看了一下别人的代码,看到这个思路,这个思路跟我第二次的想法有点儿类似,不过做了一个很强大的优化,如果节点中的num是-1的话,表示在这个节点下面有多种颜色,需要往下查询,如果num不为-1,则这个节点下面只有一种颜色,颜色的值即num的值。

非常精彩的优化。

#include<stdio.h>
#include<string.h>
#define N 100005
struct node
{
	int x,y;
	int num;
}a[N*3];
int mark[35];
void CreatTree(int t,int x,int y)
{
	a[t].x=x;
	a[t].y=y;
	a[t].num=1;
	if(x==y)
		return ;
	int temp=t*2;
	int mid=(x+y)/2;
	CreatTree(temp,x,mid);
	CreatTree(temp+1,mid+1,y);
	return ;
}
void InsertTree(int t,int x,int y,int k)
{
	if(a[t].x==x&&a[t].y==y)
	{
		a[t].num=k;
		return ;
	}
	int temp=t*2;
	int mid=(a[t].x+a[t].y)/2;
	if(a[t].num==k)
		return ;
	if(a[t].num!=-1)
	{
		a[temp].num=a[t].num;
		a[temp+1].num=a[t].num;
		a[t].num=-1;
	}
	if(y<=mid)
		InsertTree(temp,x,y,k);
	else if(x>mid)
		InsertTree(temp+1,x,y,k);
	else
	{
		InsertTree(temp,x,mid,k);
		InsertTree(temp+1,mid+1,y,k);
	}
	return ;
}
void FindTree(int t,int x,int y)
{
	if(a[t].num!=-1)
	{
		mark[a[t].num]=1;
		return ;
	}
	int temp=t*2;
	int mid=(a[t].x+a[t].y)/2;
	if(y<=mid)
		FindTree(temp,x,y);
	else if(x>mid)
		FindTree(temp+1,x,y);
	else
	{
		FindTree(temp,x,mid);
		FindTree(temp+1,mid+1,y);
	}
	return ;
}
int main()
{
	int n,m,t;
	while(scanf("%d%d%d",&n,&t,&m)!=EOF)
	{
		CreatTree(1,1,n);
		char s[5];
		int x,y,z;
		while(m--)
		{
			scanf("%s",s);
			if(s[0]=='C')
			{
				scanf("%d%d%d",&x,&y,&z);
				int temp;
				if(x>y)
				{
					temp=x;
					x=y;
					y=temp;
				}
				InsertTree(1,x,y,z);
			}
			else
			{
				scanf("%d%d",&x,&y);
				int temp;
				if(x>y)
				{
					temp=x;
					x=y;
					y=temp;
				}
				int i,sum;
				sum=0;
				memset(mark,0,sizeof(mark));
				FindTree(1,x,y);
				for(i=1;i<=t;i++)
					if(mark[i])
						sum++;
				printf("%d
",sum);
			}
		}
	}
	return 0;
}


原文地址:https://www.cnblogs.com/dyllove98/p/3206607.html