Count the Colors

这道题挺不错的,但我总是卡在一些细节上,这道题也可以用并查集做,而且时间和空间效率都比线段树高(线段树的一些区间问题可以用并查集来解决)

题解:

如果我讲的不清楚请看这位博主的文章:点击打开链接

首先,题意是在一些区间内涂色,求每种颜色色块的个数(如果这种颜色不能看见,则不需要输出这种颜色的色块个数),注意这些点和颜色的范围是0~8000,而不是0~n;左端点必定小于右端点(已验证);题目给出的是端点,而不是区间的序号,不巧的是线段树的区间修改需要的区间的序号这就需要对这些端点值进行更正(并且线段树不能把0作为区间的序号,否则会死循环,已验证)如图所示:


根据这个图来看第一组样例

0 4 4
0 3 1
3 4 2
0 2 2
0 2 3

第一行,左端点0,右端点4,修改的区间为1~4

第二行,左端点0,右端点3,修改的区间为1~3

第一行,左端点3,右端点4,修改的区间为4

第一行,左端点0,右端点2,修改的区间为1~2

第一行,左端点0,右端点2,修改的区间为1~2

由此可知,修改的区间为左端点+1,右端点不变

其次,在使用线段树时只需要一个col数组(记录颜色编号)初始化为-1(因为存在0号颜色),根据题意需要区间更新、区间查询,在更新线段树时col的值即可作为pushdown函数需要的懒惰标记(col[i]=-1时,不更新子节点,否则,更新子节点),当父节点已经是子节点需要涂的颜色时,直接return,不需要再对子节点进行更新,在query函数中需要对所有树叶结点进行拷贝放入一个数组中,方便查询

最后,查询色块个数,只要相邻的颜色不同就视为不同的色块

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


#include<stdio.h>
#include<string.h>
#define maxn 8005
int an[maxn],col_num[maxn],col[4*maxn]; 
void update(int i,int ql,int qr,int data,int left,int right);
void query(int i,int left,int right);
void pushdown(int i,int left,int right);
int main()
{
	int n;
	while(scanf("%d",&n)!=EOF)
	{
		memset(col,-1,sizeof(col));
		memset(an,-1,sizeof(an));
		memset(col_num,0,sizeof(col_num));
		for(int i=0;i<n;i++)
		{
			int a,b,c;
			scanf("%d%d%d",&a,&b,&c);
			if(a>=b)
				continue;
			update(1,a+1,b,c,1,8000);
		}
		query(1,1,8000);
		for(int i=0;i<=8000;i++)
		{
			if(an[i+1]!=an[i]&&an[i]!=-1)
				col_num[an[i]]++;
		} 	
		for(int i=0;i<=8000;i++)
		{
			if(col_num[i])
				printf("%d %d\n",i,col_num[i]);	
		}	
		putchar('\n');	
	}
	return 0;
}
void update(int i,int ql,int qr,int data,int left,int right)
{
	if(ql<=left&&qr>=right)
	{
		col[i]=data;
		return ;
	}
	if(col[i]==data)
		return ;
	pushdown(i,left,right);
	int mid=(left+right)>>1;
	if(ql<=mid)
		update(i<<1,ql,qr,data,left,mid);
	if(qr>=mid+1)
		update(i<<1|1,ql,qr,data,mid+1,right);
}
void query(int i,int left,int right)
{
	if(col[i]>=0)
	{
		for(int j=left;j<=right;j++)
			an[j]=col[i];
		return ;
	}
	if(left==right)
		return ;
	pushdown(i,left,right);
	int mid=(left+right)>>1;
	query(i<<1,left,mid);
	query(i<<1|1,mid+1,right);	
	
}
void pushdown(int i,int left,int right)
{
	if(col[i]>=0)
	{
		col[i<<1]=col[i];
		col[i<<1|1]=col[i];
		col[i]=-1;
	}
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Let 𝑃 be a set of 𝑛 points on the 𝑥-axis and each of the points is colored with one of the colors 1,2, . . . , 𝑘. For each color 𝑖 of the 𝑘 colors, there is at least one point in 𝑃 which is colored with 𝑖. For a set 𝑃 ′ of consecutive points from 𝑃, if both 𝑃 ′ and 𝑃 ∖ 𝑃 ′ contain at least one point of each color, then we say that 𝑃 ′ makes a double rainbow. See the below figure as an example. The set 𝑃 consists of ten points and each of the points is colored by one of the colors 1, 2, 3, and 4. The set 𝑃 ′ of the five consecutive points contained in the rectangle makes a double rainbow. Given a set 𝑃 of points and the number 𝑘 of colors as input, write a program that computes and prints out the minimum size of 𝑃 ′ that makes a double rainbow. Input Your program is to read from standard input. The input starts with a line containing two integers 𝑛 and 𝑘 (1 ≤ 𝑘 ≤ 𝑛 ≤ 10,000), where 𝑛 is the number of the points in 𝑃 and 𝑘 is the number of the colors. Each of the following 𝑛 lines consists of an integer from 1 to 𝑘, inclusively, and the 𝑖-th line corresponds to the color of the 𝑖-th point of 𝑃 from the left. Output Your program is to write to standard output. Print exactly one line. The line should contain the minimum size of 𝑃 ′ that makes a double rainbow. If there is no such 𝑃 ′ , print 0. The following shows sample input and output for two test cases.
最新发布
07-23
Sure! Here's an example C++ code that solves the problem: ```cpp #include <iostream> #include <vector> #include <unordered_set> int findMinimumSizeOfDoubleRainbow(const std::vector<int>& colors, int k) { int n = colors.size(); std::vector<int> colorCount(k + 1, 0); std::unordered_set<int> leftColors; int minSize = n + 1; // Iterate over all possible sizes of P' from 1 to n for (int size = 1; size <= n; size++) { // Reset color counts and left colors for each size std::fill(colorCount.begin(), colorCount.end(), 0); leftColors.clear(); // Count colors in the first size elements for (int i = 0; i < size; i++) { colorCount[colors[i]]++; leftColors.insert(colors[i]); } bool foundDoubleRainbow = true; // Check if there exists a valid P' of size 'size' for (int i = 0; i < n - size + 1; i++) { // Check if all colors are present in both P' and P \ P' if (leftColors.size() == k && colorCount == std::vector<int>(k + 1, 1)) { minSize = std::min(minSize, size); foundDoubleRainbow = true; break; } // Update color counts and left colors colorCount[colors[i]]--; if (colorCount[colors[i]] == 0) { leftColors.erase(colors[i]); } colorCount[colors[i + size]]++; leftColors.insert(colors[i + size]); } if (!foundDoubleRainbow) { break; } } return (minSize == n + 1) ? 0 : minSize; } int main() { int n, k; std::cin >> n >> k; std::vector<int> colors(n); for (int i = 0; i < n; i++) { std::cin >> colors[i]; } int minSize = findMinimumSizeOfDoubleRainbow(colors, k); std::cout << minSize << std::endl; return 0; } ``` You can compile and run this code to solve the problem. It reads the input from standard input and prints the minimum size of 𝑃 ′ that makes a double rainbow to standard output. Note: This code assumes that the input is valid and follows the given constraints. You may need to add additional input validation if necessary.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值