【线段树】线段树练习题二

线段树练习题二

题目

桌子上零散地放着若干个不同颜色的盒子,桌子的后方是一堵墙。如右图所示。问从桌子前方可以看到多少个盒子?假设人站得足够远(输入时,由底向上,从左到右)。

输入样例

16//桌子长度
5//盒子数量
4 7
12 14
1 5
6 10
11 16

输入样例

4

数据范围

1<=n<=100000,1<=m<=100000,保证坐标范围为[1,n].

解题思路

其实这道题就是一道线段树,先把每个盒子的起始点和终点都先插入到树中,然后用 c o l o r color color来定义每个盒子的颜色,然后看是否有覆盖的颜色,然后统计树即可.

程序如下

#include
#include
#include
#include
using namespace std;
int n,m,x,y,ans,b[100001];

struct t
{
	int l,r,colorx;
}tree[400001];

void Build(int x,int L,int R)//建树
{
	tree[x].l=L; tree[x].r=R;
	if(L + 1 == R) return;
	int mid=(L+R)>>1;
	Build(x*2,L,mid);
	Build(x*2+1,mid,R);
	return;
}

void Ins(int x,int L,int R,int color)//插入
{
	if (tree[x].l == L && tree[x].r == R) 
	   tree[x].colorx = color;
	else
	{
		if (tree[x].colorx >= 0)
		{
			tree[x*2].colorx = tree[x].colorx;
			tree[x*2+1].colorx = tree[x].colorx;
			tree[x].colorx = -1;
		}
		int mid = (tree[x].l + tree[x].r) >> 1;
		if (R <= mid) Ins (x * 2,L,R,color);
		else if (L >= mid) Ins (x * 2 + 1,L,R,color);
		else {
			Ins (x * 2,L,mid,color);
			Ins (x * 2 + 1,mid ,R,color);
		}
	}
	 
}

void Count (int x)//统计
{
	if (tree[x].colorx >= 0)
		b[tree[x].colorx] = true; 
	else if(tree[x].l+1 < tree[x].r)
	{
		Count(x * 2);
		Count(x * 2 + 1);
	}
}

int main()
{
	scanf("%d%d",&n,&m);
	Build(1,1,n);
	for (int i=1; i<=m; ++i)
	{
		scanf("%d%d",&x,&y);
		Ins(1,x,y,i);
	}
	Count(1);
	for(int i = 1;i <= m; ++i)
		if(b[i] == true) ans++;
	printf("%d",ans);
	return 0;
}

你可能感兴趣的:(线段树)