您的位置:首页 > 其它

poj 2777 Count Color

2015-01-03 20:20 218 查看
问题描述:http://poj.org/problem?id=2777

理解:

一道线段树的题。

统计一块木板上出现颜色的种类。相对纯粹和的累加还是不一样。涂上新的颜色会被覆盖掉,找不到合适的容器。

还有lazy算法,避免每一次搜索得把所有叶子节点遍历一遍

细节:

1."P A B" (here A, B, C are integers, and A may be larger than B) 意味着出现此种情况要交换

2.节点里还是不要Mid(),占空间。

解决办法:

1.用一个32位的整数,记录每一种颜色出现。解决覆盖可以用左右叶子节点 | 。计算颜色种数用移位>>。

2.两个操作

Color()这个函数的递归让我挺晕的。据我目前看来的递归函数,在调用自身之前常往下一步走,也就是“push up”, 调用自身之后,会反馈回来,

也就是“push down”。查询这个操作里,因为要用lazy算法,终止条件几乎都是,当前节点范围被s、e覆盖。

Output()这个函数里要返回颜色这个32位整数。在最后一个判断条件里是用符号 | 进行种数的累加,而不是单纯的加和,我就wa在这里了。

3.标记flag为1的时候表示只有当前区间只有一种颜色(可以选择push down);为0的时候就已经有多种颜色了。

代码:

#include <iostream>
#include <cstdio>

#define N 100050

using namespace std;

struct Node
{
int L, R, flag;
int C;    //32位整数
int Mid()
{
return (L + R)/2;
}
} tree[N * 4];

int amount(int c)
{
int a = 0;
while(c != 0)
{
if((c & 1) == 1)
{
a++;
}
c >>= 1;
}
return a;
}
/*
void print(int root)
{
cout << tree[root].L << " " << tree[root].R << endl;
cout << tree[root].flag << endl;
cout << amount(tree[root].C) << endl << endl;
}
*/

void BuildTree(int root, int L, int R)
{
tree[root].L = L;
tree[root].R = R;
tree[root].C = 1;
tree[root].flag = 1;//

if(L != R)
{
BuildTree(root * 2 + 1, L, (L + R)/2);
BuildTree(root * 2 + 2, (L + R)/2 + 1, R);
}
}

void color(int root, int s, int e, int t)
{
if(s <= tree[root].L && tree[root].R <= e)
{
tree[root].C = (1 << (t - 1));
tree[root].flag = 1;
//print(root);
return;
}
if(tree[root].flag)
{
tree[root * 2 + 1].C = tree[root * 2 + 2].C = tree[root].C;
tree[root * 2 + 1].flag = tree[root * 2 + 2].flag = 1;
tree[root].flag = 0;
}

if(e <= tree[root].Mid())
{
color(root * 2 + 1, s, e, t);
}
else if(s > tree[root].Mid())
{
color(root * 2 + 2, s, e, t);
}
else
{
color(root * 2 + 1, s, tree[root].Mid(), t);
color(root * 2 + 2, tree[root].Mid() + 1, e, t);
}
tree[root].C = tree[root * 2 + 1].C | tree[root * 2 + 2].C;
tree[root].flag = 0;
}

int output(int root, int s, int e)
{
if((s <= tree[root].L && tree[root].R <= e) || tree[root].flag)
{
return tree[root].C;
}

if(e <= tree[root].Mid())
{
return output(root * 2 + 1, s, e);
}
else if(s > tree[root].Mid())
{
return output(root * 2 + 2, s, e);
}
else
{
return output(root * 2 + 1, s, tree[root].Mid()) | output(root * 2 + 2, tree[root].Mid() + 1, e);
}

}

int main()
{
int L, T, O;
scanf("%d%d%d", &L, &T, &O);
//cin >> L >> T >> O;

BuildTree(0, 1, L);

for(int i = 0; i < O; i++)
{
char c;
int s, e, t;

getchar();
scanf("%c", &c);
//cin >> c;
if(c == 'C')
{
scanf("%d%d%d", &s, &e, &t);
//cin >> s >> e >> t;
color(0, s, e, t);
/*
for(int i = 0; i <  L + 1; i++)
{
print(i);
}
*/

}
else if(c == 'P')
{
scanf("%d%d", &s, &e);
//cin >> s >> e;
if(s > e)
swap(s, e);

printf("%d\n", amount(output(0, s, e)));
//cout << A << endl;
}
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: