【線段樹】線段樹練習題二

線段樹練習題二

題目

桌子上零散地放着若干個不同顏色的盒子,桌子的後方是一堵牆。如右圖所示。問從桌子前方可以看到多少個盒子?假設人站得足夠遠(輸入時,由底向上,從左到右)。

輸入樣例

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

輸入樣例

4

數據範圍

1<=n<=100000,1<=m<=100000,保證座標範圍爲[1,n].

解題思路

其實這道題就是一道線段樹,先把每個盒子的起始點和終點都先插入到樹中,然後用colorcolor來定義每個盒子的顏色,然後看是否有覆蓋的顏色,然後統計樹即可.

程序如下

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章