ZOJ1610 Count the Colors(线段树区间更新)

链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1610

题意:一块8000长度的板子,每次覆盖啊(a,b)的格子颜色为c。覆盖的时候不包括两个端点

样例解释:

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

1 1
2 1
3 1

5是5步操作,板子8000长度是不变的


输出为:

颜色为1的有1段,颜色为2的有1段,颜色为3的有1段


代码:

#include<iostream>  
#include<cstring>  
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;

#define calm (l+r)/2
#define lson l,m,rt*2
#define rson m+1,r,rt*2+1
#define maxn 8010

int sum[maxn * 4];
/*
原本应该用一个add数组来记录是否延迟的
但是对于这个题目来说,除了叶子节点的节点都是没什么用的,
所以直接用这个树上的非叶子节点来表示是否延迟,节省了空间
*/
int ans[8010],temp[8010];

inline void Pushdown(int rt)
{
	if (sum[rt]!=-1)
	{
		sum[rt * 2] = sum[rt];
		sum[rt * 2 + 1] = sum[rt];
		sum[rt] = -1;//不是叶子节点,用-1表示未延迟
	}
}
void update(int L,int R,int c,int l,int r,int rt)
{
	if (L <= l&&r <= R)
	{
		sum[rt] = c;//标记
		return;
	}
	Pushdown(rt);
	int m = calm;
	if (L <= m)
		update(L, R, c, lson);
	if (R > m)
		update(L, R, c, rson);
}
void query(int l,int r,int rt)
{
	if (l == r)//叶子结点
	{
		temp[l] = sum[rt];//记录下当前格子的颜色是什么
		return;
	}
	Pushdown(rt);
	int m = calm;
	query(lson);
	query(rson);
}
int main()
{
//	freopen("D://input.txt", "r", stdin);
//	freopen("D://output.txt", "w", stdout);
	int n;
	while (scanf("%d", &n) != EOF)
	{
		memset(ans, 0, sizeof(ans));
		memset(sum, -1, sizeof(sum));//build(),每次build都要建立到8000,所以直接memset也是一样的
		while (n--)
		{
			int a, b, c;
			scanf("%d%d%d", &a, &b, &c);
			update(a + 1, b, c, 1, 8000, 1);//所有格子往后移一格,用i表示这个【i,i-1】区间
		}
		query(1,8000,1);
		if (temp[1] != -1)
			ans[temp[1]]++;
		/*
		因为往后移了一格,原本是【0,8000】,就变成【1,8001】
		但是因为8001是用来表示【8000,8001】这个区间的
		这个区间不存在,所以枚举格子时到8000就可以了
		*/
		for (int i = 2; i <= 8000; i++)//枚举格子
		{
			if (temp[i]!=-1&&temp[i] != temp[i - 1])
				ans[temp[i]]++;
		}
		for (int i = 0; i <= 8000; i++)//枚举颜色
		{
			if (ans[i] != 0)
				printf("%d %d\n", i, ans[i]);
		}
		printf("\n");
	}
//	printf("%.6lf\n",(double)clock()/CLOCKS_PER_SEC);
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值