ZOJ 1610 Count the Colors

31 篇文章 0 订阅
19 篇文章 0 订阅

Problemacm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1610

Referenceblog.csdn.net/shuangde800/article/details/8186332

分析:线段树成段更新,错在两个地方。

第一点,题中给出的边界是线段的两个端点,也就是说每个标号表示一个点而不是一个小线段。

于是我采用标号表示它右边的一段,所以输入“x1 x2 c”,我处理成:update(x1, x2-1, c, ...)。

第二点,连在一起的两段同色段要合并成一大段,但不能简单写个 pushup() 来完成,因为两个同色段可能分在两个结点所管的区间内,但又没有结点所管的区间那么长,所以会出现漏合并的情况。于是多开一个 c 数组,在 query 的时侯,把更新完的最后结果都放进这个数组中,然后再用一个循环找颜色段。

Source Code

#include <cstdio>
#include <cstring>
using namespace std;
const int N = 8000;

int tree[N+5<<2];
int cnt[N+1]; // cnt[i]表示第i种色的段数
int c[N]; // c[i]表示第i段的颜色(0<=i<N)

/*
void pushup(int x)
{
	if(~tree[x<<1] && tree[x<<1] == tree[x<<1|1])
		tree[x] = tree[x<<1];
}
*/

void pushdown(int x)
{
	if(~tree[x])
	{
		tree[x<<1] = tree[x<<1|1] = tree[x];
		tree[x] = -1;
	}
}

void update(int ul, int ur, int v, int l, int r, int id)
{
	if(ul <= l && r <= ur)
	{
		tree[id] = v;
		return;
	}
	pushdown(id);
	int m = l + r >> 1;
	if(ul <= m)
		update(ul, ur, v, l, m, id<<1);
	if(ur > m)
		update(ul, ur, v, m+1, r, id<<1|1);
//	pushup(id);
}

void query(int l, int r, int id)
{
	if(~tree[id])
	{
//		++cnt[tree[id]];
		for(int i=l,col=tree[id]; i<=r; ++i)
			c[i] = col;
		return;
	}
	if(l == r) return;
	int m = l + r >> 1;
	query(l, m, id<<1);
	query(m+1, r, id<<1|1);
}

int main()
{
	int n;
	while(~scanf("%d", &n))
	{
		memset(tree, -1, sizeof tree);
		for(int a,b,v; n--; )
		{
			scanf("%d%d%d", &a, &b, &v);
			update(a, b-1, v, 0, N-1, 1);
		}
		memset(c, -1, sizeof c);
		query(0, N-1, 1);
		memset(cnt, 0, sizeof cnt);
		for(int i=0; i<N; ++i)
		{
			if(c[i] == -1) continue;
			++cnt[c[i]];
			for(int j=i+1; j<N && c[j]==c[i]; ++j)
				i = j;
		}
		for(int i=0; i<=N; ++i)
			if(cnt[i])
				printf("%d %d\n", i, cnt[i]);
		putchar('\n');
	}
	return 0;
}

注释掉的就是之前用 pushup() 的错误代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值