您的位置:首页 > 其它

POJ 2777 Count Color(线段树 + 状态压缩)

2015-12-06 22:36 369 查看
题目大意:

长度为L的一块板, 被分为L个长度为1的小板,编号为1 ~ L。有两种操作,操作C后面跟三个数A,B,C,代表第A块板到第B块板涂上颜色C,操作B后面A,B,需要你输出第A块板到第B块板上共有多少种不同的颜色。颜色的种类最多30种,L和操作数最大都是10万。

解题思路:

很明显的线段树。问题的关键是怎么保存、更新、询问树上每个节点上有哪些颜色。看到颜色的种类不会大于30种这个条件,我相信很多人都会窃喜,这不就是状态压缩么?更新的时候用一个“位或”操作就行了。

大概的思路也真的是这样。这道题目我是敲了很久,可能线段树真的是我的薄弱点吧。不过每一段代码我都是用心去写的,希望勿喷!

Show me the code!

#include <iostream>
#include <cstdio>
#define mid l + (r - l) / 2
#define lson id << 1, l, mid
#define rson id << 1 | 1, mid + 1, r
using namespace std;
const int MAXN = 1e5;
int tree[MAXN * 4], laze[MAXN * 4], ans;
void build(int id, int l, int r) {
laze[id] = 0;
if (l == r) {
tree[id] = 1;
}
else {
build(lson);
build(rson);
tree[id] = tree[id << 1] | tree[id << 1 | 1];
}
}
void pushdown(int id) {
tree[id << 1] = laze[id];
laze[id << 1] = laze[id];
tree[id << 1 | 1] = laze[id];
laze[id << 1 | 1] = laze[id];
laze[id] = 0;
}
void updata(int id, int l, int r, int L, int R, int val) {
if (R < l || L > r) return;
if (L <= l && r <= R) {
tree[id] = val;
laze[id] = val;
return;
}
if (laze[id]) pushdown(id);
updata(lson, L, R, val);
updata(rson, L, R, val);
tree[id] = tree[id << 1] | tree[id << 1 | 1];
}
void query(int id, int l, int r, int L, int R) {
if (R < l || L > r) return;
if (L <= l && r <= R) {
ans |= tree[id];
return;
}
if (laze[id]) pushdown(id);
query(lson, L, R);
query(rson, L, R);
tree[id] = tree[id << 1] | tree[id << 1 | 1];
}
int count(unsigned int N) {
int res = 0;
while (N) {
res += N & 1;
N >>= 1;
}
return res;
}
int main() {
int L, T, O;
scanf("%d%d%d", &L, &T, &O);
build(1, 1, L);
for (int a = 0; a < O; ++a) {
char op;
getchar();
scanf("%c", &op);
if (op == 'C') {
int b, c, d;
scanf("%d%d%d", &b, &c, &d);
if (b > c) swap(b, c);
updata(1, 1, L, b, c, 1 << (d - 1));
}
else {
int b, c;
scanf("%d%d", &b, &c);
if (b > c) swap(b, c);
ans = 0;
query(1, 1, L, b, c);
printf("%d\n", count(ans));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj