【线段树】SSLOJ 2645 线段树练习二

L i n k Link Link

SSL 2645

D e s c r i p t i o n Description Description

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

I n p u t Input Input

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

O u t p u t Output Output

4

H i n t Hint Hint

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

T r a i n Train Train o f of of T h o u g h t Thought Thought

用线段树做
设一个参数color,为当前区间的颜色(若只有一种,为颜色编号,否则就为-1)

C o d e Code Code

#include<cstdio>
#include<iostream>

using namespace std;

int n, b[100005], ans, m, l, r;

struct Tree
{
	int l, r, colorx;
}t[400005];//定义树啦

void Build(int x, int left, int right)
{
	t[x].l = left; t[x].r = right;
	if (left + 1 == right) return;
	int mid = (left + right) >> 1;
	Build(x * 2, left, mid);
	Build(x * 2 + 1, mid, right);
	return;
}//建立线段树
void Ins(int x, int L, int R, int color)
{
	if (L == t[x].l && R == t[x].r) 
		t[x].colorx = color;
	else {
		if (t[x].colorx >= 0)
		{
			t[x * 2].colorx = t[x * 2 + 1].colorx = t[x].colorx;
			t[x].colorx = -1;
		}//把颜色往下传
		int mid = (t[x].l + t[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)
{
	int mid = (t[x].l + t[x].r) >> 1;
	if (t[x].colorx >= 0) b[t[x].colorx] = true;
    else if (t[x].l + 1 < t[x].r) { 
		Count(x * 2); 
		Count(x * 2 + 1);
	} 
}//统计有多少种颜色

int main()
{
	int col = 0;
	scanf("%d%d", &n, &m);
	Build(1, 1, n);
	for (int i = 1; i <= m; ++i)
	{
		scanf("%d%d", &l, &r);
		Ins(1, l, r, ++col);
	}
	Count(1);
	for (int i = 1; i <= col; ++i)
		if (b[i] == true) ans++;//因为0不算一种颜色
	printf("%d",ans);
}

我真的是智障 ,没算零还减了1.。。卡了快一晚上了。。。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值