POJ 2777

by 华师小刚

需要注意:

1.线段树数组开400000个

2.初始颜色都为1

3.有多组测试数据

4.用STL记录答案会超时

5.输入是给出x块到y块,不是区间,而且x的序号可能大于y的序号。

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <algorithm>

using namespace std;

const int N = 400000 + 10;

bool vis[31];

struct Node
{
	Node():l(-1), r(-1), k(1) {}
	int l, r;
	int k;//-1表示该区间未被完全覆盖
	
}st[N];

void BuildTree(int pos, int a, int b)
{
	st[pos].l = a;
	st[pos].r = b;
	st[pos].k = 1;
	if (b - a == 1) return;
	int mid = (a + b) / 2;
	BuildTree(pos * 2 + 1, a, mid);
	BuildTree(pos * 2 + 2, mid, b);
}

void modify(int pos, int a, int b, int c) //区间(a, b)涂 c
{
	if (st[pos].l == a && st[pos].r == b)
	{
		st[pos].k = c;
		return;
	}
	if (st[pos].k > 0)//将信息往下传
	{
		st[pos * 2 + 1].k = st[pos].k;
		st[pos * 2 + 2].k = st[pos].k;
	}

	st[pos].k = -1;//表示该节点没被完全覆盖

	int mid = (st[pos].l + st[pos].r) / 2;
	if (b <= mid)
	{
		modify(pos * 2 + 1, a, b, c);
	}
	else if (a >= mid)
	{
		modify(pos * 2 + 2, a, b, c);
	}
	else
	{
		modify(pos * 2 + 1, a, mid, c);
		modify(pos * 2 + 2, mid, b, c);
	}
}

void count(int pos, int a, int b)
{
	if (st[pos].k != -1 && a >= st[pos].l && b <= st[pos].r)
	{
		vis[st[pos].k] = 1;
		return;
	}
	int mid = (st[pos].l + st[pos].r) / 2;
	if (b <= mid)
	{
		count(pos * 2 + 1, a, b);
	}
	else if (a >= mid)
	{
		count(pos * 2 + 2, a, b);
	}
	else
	{
		count(pos * 2 + 1, a, mid);
		count(pos * 2 + 2, mid, b);
	}
	
}

void init()
{
	for (int i = 1; i <= 30; ++i)
	{
		vis[i] = 0;
	}
}

int main()
{
	int L, T, O;
	while (scanf("%d%d%d", &L, &T, &O) != EOF)
	{
		BuildTree(0, 0, L);
		char op[2];
		
		for (int i = 1; i <= O; ++i)
		{
			scanf("%s", &op);
			if (op[0] == 'C')
			{
				int x, y, c;
				scanf("%d%d%d", &x, &y, &c);
				if (x > y) swap(x, y);
				modify(0, x - 1, y, c);
				continue;
			}

			init();
			int x, y;
			scanf("%d%d", &x, &y);
			if (x > y) swap(x, y);
			count(0, x - 1, y);
			int res = 0;
			for (int i = 1; i <= 30; ++i)
			{
				if (vis[i] == 1) res++;
			}
			printf("%d\n", res);
		}
		
	}
	return 0;
}

测试数据:

10 4 5
C 2 1 3
C 9 10 2
C 5 5 4
P 1 5
P 2 2

12 5 10
C 3 2 4
C 5 4 2
P 6 5
C 1 2 2
C 2 3 2
C 4 4 1
P 2 3
P 7 7
C 8 12 5
P 1 12

6 7 4
C 1 6 2
P 1 5
C 4 2 7
P 6 1

5 3 5
C 1 3 2
P 2 4
C 3 5 3
P 1 5
P 3 4

答案:
3
1

2
1
1
3

1
2

2
2
1

                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值