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!
长度为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; }
相关文章推荐
- 初学ACM - 组合数学基础题目PKU 1833
- POJ ACM 1001
- POJ ACM 1002
- POJ 2635 The Embarrassed Cryptographe
- POJ 3292 Semi-prime H-numbers
- POJ 2773 HAPPY 2006
- POJ 3090 Visible Lattice Points
- POJ-2409-Let it Bead&&NYOJ-280-LK的项链
- POJ-1695-Magazine Delivery-dp
- POJ1523 SPF dfs
- POJ-1001 求高精度幂-大数乘法系列
- POJ-1003 Hangover
- POJ-1004 Financial Management
- 用单调栈解决最大连续矩形面积问题
- 2632 Crashing Robots的解决方法
- 1573 Robot Motion (简单题)
- POJ 1200 Crazy Search(简单哈希)
- 【高手回避】poj3268,一道很水的dijkstra算法题
- POJ 1088 滑雪
- poj2387 Til the Cows Come Home—Dijkstra模板