一道跟POJ2777线段树基本一样的题,不同点就在于输出时这道题是按照颜色id从小到大输出而不是输出颜色。简单讲一下题意:给围墙染色,P操作代表给坐标为[a,b]的墙染上id为c的颜色,而Q操作表示询问在[a,b]范围内的围墙颜色种类,并且按照升序输出颜色id。
我的解题思路:肯定和POJ2777线段树一样,使用一个32位整型数来存储颜色(因为有30种颜色,所以不需要开一个长度为30的bool数组,事实上这样是导致TLE的关键)。使用按位或运算计算出范围颜色然后用一个整型数存储。最后写个函数顺序输出id就ok了。
我的解题代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <ctime>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <list>
#include <map>
using namespace std;
#define N 1000000
struct tree //定义线段树结构体
{
int left;
int right;
int mid;
int color; //这个代表当前范围的颜色
int set; //延迟标记
void init()
{
mid = (left + right) >> 1;
color = 2; //初始颜色为2
set = 0;
return;
}
};
tree node[N<<2];
int ans;
int n, m;
void BuildTree(int left, int right, int x); //建立线段树
void P(int left, int right, int co, int x); //P操作
int Q(int left, int right, int x); //Q操作
void PushUp(int x); //向上更新
void PushDown(int x); //向下更新
int main()
{
char ch;
int a, b, c;
while (~scanf("%d %d", &n, &m))
{
if (n == m && m == 0) break;
BuildTree(1, n, 1);
while (m--)
{
scanf(" %c %d %d", &ch, &a, &b);
if (ch == 'P')
{
scanf("%d", &c);
P(a, b, c, 1);
}
else
{
ans = Q(a, b, 1);
bool flag = false; //为了使除了最后一个颜色后面输出换行其他都输出一个空格
for (int i=1; i<=30; ++i)
{
if ((ans & 1) == 1)
{
if (flag) putchar(' ');
printf("%d", i);
flag = true;
}
ans >>= 1;
}
putchar('\n');
}
}
}
return 0;
}
void BuildTree(int left, int right, int x)
{
node[x].left = left;
node[x].right = right;
node[x].init();
if (left == right) return;
BuildTree(left, node[x].mid, x << 1);
BuildTree(node[x].mid + 1, right, x << 1 | 1);
return;
}
void P(int left, int right, int co, int x)
{
if (node[x].left == left && node[x].right == right)
{
int num = 1; //颜色id所转换的数
for (int i=1; i<co; ++i) num <<= 1; //将颜色id转换为颜色数
node[x].set = num;
node[x].color = num; //这里注意=不要写成|=,就因为这地方错WA了好久...
PushUp(x);
return;
}
if (node[x].set != 0) PushDown(x);
if (right <= node[x].mid)
{
P(left, right, co, x << 1);
}
else if (left > node[x].mid)
{
P(left, right, co, x << 1 | 1);
}
else
{
P(left, node[x].mid, co, x << 1);
P(node[x].mid + 1, right, co, x << 1 | 1);
}
return;
}
void PushUp(int x)
{
while (x != 1)
{
x >>= 1;
node[x].color = node[x<<1].color | node[x<<1|1].color;
}
return;
}
void PushDown(int x)
{
node[x<<1].color = node[x<<1|1].color = node[x].color;
node[x<<1].set = node[x<<1|1].set = node[x].set;
node[x].set = 0;
return;
}
int Q(int left, int right, int x)
{
if (node[x].left == left && node[x].right == right)
{
return node[x].color;
}
if (node[x].set != 0) PushDown(x);
if (right <= node[x].mid)
{
return Q(left, right, x << 1);
}
if (left > node[x].mid)
{
return Q(left, right, x << 1 | 1);
}
return Q(left, node[x].mid, x << 1) | Q(node[x].mid + 1, right, x << 1 | 1);
}