ZOJ - 1610 Count the Colors(以区间为”点“的线段树)

Count the Colors


Time Limit: 2 Seconds      Memory Limit: 65536 KB


Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent ones.

Your task is counting the segments of different colors you can see at last.


Input

The first line of each data set contains exactly one integer n, 1 <= n <= 8000, equal to the number of colored segments.

Each of the following n lines consists of exactly 3 nonnegative integers separated by single spaces:

x1 x2 c

x1 and x2 indicate the left endpoint and right endpoint of the segment, c indicates the color of the segment.

All the numbers are in the range [0, 8000], and they are all integers.

Input may contain several data set, process to the end of file.


Output

Each line of the output should contain a color index that can be seen from the top, following the count of the segments of this color, they should be printed according to the color index.

If some color can't be seen, you shouldn't print it.

Print a blank line after every dataset.


Sample Input

5
0 4 4
0 3 1
3 4 2
0 2 2
0 2 3
4
0 1 1
3 4 1
1 3 2
1 3 1
6
0 1 0
1 2 1
2 3 1
1 2 0
2 3 0
1 2 1


Sample Output

1 1
2 1
3 1

1 1

0 2
1 1

 

          这道题大体意思就是,本来是一段无色的区间,然后进行n步操作来进行染色,在最后的时候分别输出以各种颜色为基准的区间数量有多少。

          这道题最重要的一点就是这是区间的染色!!不能和平常的点集的建树和改变一样操作。我仿照kuangbin大佬的模板写了一遍,顺便记录心得~~在代码中给出; 

 

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 8010;
struct ***
{
	int l, r, col;
}tr[maxn<<2];//所建之树
int color[maxn];//每种颜色的区间数量
int temp;//用来判断区间前后的颜色是否连续
void build(int rt, int l, int r)
{
	tr[rt].l = l;
	tr[rt].r = r;
	tr[rt].col = -1;
	if (l + 1 == r)//不能出现点的请况
	{
		return;
	}
	int mid = ((l + r) >> 1);
	build(rt << 1, l, mid);
	build(rt << 1 | 1, mid, r);//这里不同的是;两个都是mid,从而达到了题目中所需的把区间作为点的实现;
}
void insert(int rt, int l, int r, int c)
{
	if (l == r)return;//点的情况
	if (tr[rt].col == c)return;//如果本来颜色相同,就不用继续了
	if (l <= tr[rt].l&&r >= tr[rt].r)//如果这段区间被包含,直接区间的改颜色就好
	{
		tr[rt].col = c;
		return;
	}
	if (tr[rt].col >= 0)//如果已经被染色过
	{
		tr[rt << 1 | 1].col = tr[rt << 1].col = tr[rt].col;//之前的颜色传下去
		tr[rt].col = -2;//标记这是存在混合颜色的情况
	}
	int mid = ((tr[rt].l + tr[rt].r) >> 1);
	if (r <= mid)//开始分情况进行染色
	{
		insert(rt << 1, l, r, c);
	}
	else if (l >= mid)
	{
		insert(rt << 1 | 1, l, r, c);
	}
	else
	{
		insert(rt << 1, l, mid, c);
		insert(rt << 1 | 1, mid, r, c);
	}
	tr[rt].col = -2;
}
void count(int s)//开始数数量
{
	if (tr[s].col == -1)
	{
		temp = -1;
		return;
	}
	if (tr[s].col != -2)//只有一个颜色
	{
		if (tr[s].col != temp)//是否与之区间区间颜色相同
		{
			color[tr[s].col]++;
			temp = tr[s].col;
		}
		return;
	}
	if (tr[s].l + 1 != tr[s].r)//存在2个以上的单位区间才进行下部操作,防止访问点;
	{
		count(s << 1);
		count(s << 1 | 1);
	}
}
int main()
{
	int n, a, b, c;
	int Max;
	while (scanf("%d", &n) != EOF)
	{
		build(1, 0, 8000);//建树
		Max = 0;//记录最大的颜色标号
		while (n--)
		{
			scanf("%d%d%d", &a, &b, &c);
			insert(1, a, b, c);
			if (c > Max)
			{
				Max = c;
			}
		}
	//	cout << Max << endl;
		temp = -1;
		memset(color, 0, sizeof(color));
		count(1);//开始计数
		for (int s = 0; s <= Max; s++)
		{
			if (color[s])printf("%d %d\n", s, color[s]);//输出;
		}
		printf("\n");
	}
}



 

全部评论

相关推荐

不亏是提前批,神仙打架,鼠鼠不配了
站队站对牛:现在92都报工艺岗了
投递韶音科技等公司7个岗位
点赞 评论 收藏
分享
头顶尖尖的程序员:我是26届的不太懂,25届不应该是找的正式工作吗?为什么还在找实习?大四还实习的话是为了能转正的的岗位吗
点赞 评论 收藏
分享
06-02 15:17
门头沟学院 Java
心爱的idea:怎么会呢 应该是打招呼有问题 问就说实习6个月全国可飞随时到岗
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
昨天 12:31
以前小时候我最痛恨出轨、偷情的人,无论男女,为什么会出轨?现在我成了自己最讨厌的人,没想到分享的东西在牛客会被这么多人看,大家的评价都很中肯,我也认同,想过一一回复,但我还是收声了,我想我应该说说这件事,这件事一直压在我心里,是个很大的心结,上面说了人为什么出轨,我大概能明白了。我们大一下半年开始恋爱,开始恋爱,我给出了我铭记3年的承诺,我对她好一辈子,我永远不会背叛,我责任心太重,我觉得跟了我,我就要照顾她一辈子,我们在一起3年我都没有碰过她,她说往东我就往东,她说什么我做什么,她要我干什么,我就干什么!在学校很美好,中途也出过一些小插曲,比如男闺蜜、男闺蜜2号等等等。但我都强迫她改掉了,我...
牛客刘北:两个缺爱的人是没有办法好好在一起的,但世界上哪有什么是非对错?你后悔你们在一起了,但是刚刚在一起的美好也是真的呀,因为其他人的出现,你开始想要了最开始的自己,你的确对不起自己,21岁的你望高物远,你完全可以不谈恋爱,去过你想要的生活,你向往自由,在一起之后,你要想的不是一个人,而是两个人,你不是变心了,就像你说的,你受够了,你不想包容了,冷静几天是你最优的选择,爱人先爱己。
社会教会你的第一课
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务