题意:长度为n(1~100000)个单位的画板,有t(1~30,位运算的可能性)种颜料。现在叫你完成m组操作:
1. "C A B C" Color the board from segment A to segment B with color C.
2. "P A B" Output the number of different colors painted between segment A and segment B (including).
思路:很经典的线段树。学习到了很多的新知识,最重要的是三点:1.延迟覆盖的操作。2.位操作,用 | 来合并颜色种类。3.updata操作时递归回来,两个子节点的信息对父节点的更新。
代码如下:
#include<iostream>
using namespace std;
const int Max = 100050;
struct
{
int l, r;
int col; // 用一个32位的int型,每一位对应一种颜色,用位运算代替bool col[32]。
bool cover; // 表示这个区间都被涂上同一种颜色,线段树效率的体现,否则插入就是0(n)了。
}node[3*Max];
void swap(int &a, int &b)
{
int tmp = a;
a = b;
b = tmp;
}
void BuildTree(int left, int right, int u)
{
node[u].l = left;
node[u].r = right;
node[u].col = 1; // 开始时都为涂有颜色1,看题要仔细,要注意状态。
node[u].cover = true;
if(left == right)
return;
int mid = (left+right)>>1;
BuildTree(left, mid, u<<1);
BuildTree(mid+1, right, (u<<1)+1);
}
void get_down(int u)
{ // 延迟覆盖的操作。
int val = node[u].col;
node[u].cover = false;
node[u<<1].col = val;
node[u<<1].cover = true;
node[(u<<1)+1].col = val;
node[(u<<1)+1].cover = true;
}
void updata(int left, int right, int val, int u)
{
if(left <= node[u].l && right >= node[u].r)
{
node[u].col = val;
node[u].cover = true;
return;
}
if(node[u].col == val)
return; // 这个剪枝还优40多MS,效果还蛮不错的。
if(node[u].cover)
get_down(u);
//node[u].col |= val; 这样是错的,因为新加入的颜色可能会把node[u].col中的某些颜色覆盖掉。
if(left <= node[u<<1].r)
updata(left, right, val, u<<1);
if(right >= node[(u<<1)+1].l)
updata(left, right, val, (u<<1)+1);
node[u].col = node[u<<1].col | node[(u<<1)+1].col; // 最后递归回来再更改父节点的颜色。
}
void query(int left, int right, int &sum, int u)
{
if(node[u].cover)
{ // 这个区间全部为1种颜色,就没有继续分割区间的必要了。
sum |= node[u].col; // 颜色种类相加的位运算代码。
return;
}
if(left <= node[u].l && right >= node[u].r)
{
sum |= node[u].col;
return;
}
if(left <= node[u<<1].r)
query(left, right, sum, u<<1);
if(right >= node[(u<<1)+1].l)
query(left, right, sum, (u<<1)+1);
}
int fun(int sum)
{ // 求int型的sum对应的颜色数量,即为求sum中有多少位是1。
int ans = 0;
while(sum)
{
if(sum % 2)
ans ++; // sum最后一位为1,(sum%2==1),则多一种颜色。
sum = sum>>1; // sum右移出一位。
}
return ans;
}
int main()
{
int n, t, m;
scanf("%d%d%d", &n, &t, &m);
BuildTree(1, n, 1);
while(m--)
{
getchar();
int a, b, c;
char ope;
scanf("%c", &ope);
if(ope == 'C')
{
scanf("%d%d%d", &a, &b, &c);
if(b < a)
swap(a, b); // 有可能b < a,要有状态仔细点,考虑要全面。
updata(a, b, 1<<(c-1), 1); // int型的右起第c位变为1,即2的c-1次方。
}
else
{
scanf("%d%d", &a, &b);
if(b < a)
swap(a, b);
int sum = 0;
query(a, b, sum, 1);
printf("%d\n", fun(sum));
}
}
return 0;
}
分享到:
相关推荐
POJ题解 个人写法 线段树每个人都不一样
* 线段树:例如 poj2528、poj2828、poj2777、poj2886、poj2750。 * 静态二叉检索树:例如 poj2482、poj2352。 * 树状树组:例如 poj1195、poj3321。 * RMQ:例如 poj3264、poj3368。 * 并查集的高级应用:例如 ...
- (poj2528, poj2828, poj2777, poj2886, poj2750):一种高效的数据结构,用于区间求和等操作。 2. **分块**: - (poj2482, poj2352):将数据分为多个区块,提高查询效率。 3. **树套树**: - (poj1195, poj...
poj2528、poj2777等是线段树的题目,poj2482、poj2352等涉及平衡树,poj1195、poj3321则训练了树状数组。 5. **搜索算法的优化**:poj1699、poj3411等训练搜索技巧和剪枝方法,poj3373、poj1691则介绍了记忆化搜索。...
- POJ 2777、POJ 2886:队列的应用。 #### 树状数组 - **题目示例**: - POJ 3264、POJ 3368:树状数组的构造与更新。 #### 字符串匹配 - **题目示例**: - POJ 1961、POJ 2406:KMP算法的应用。 ### 其他问题...
### ACM新手刷题攻略之POJ ... - 推荐题目:[poj2528](https://vjudge.net/problem/POJ-2528)、[poj2828](https://vjudge.net/problem/POJ-2828)、[poj2777](https://vjudge.net/problem/POJ-2777)、[poj2886]...
1. **高级数据结构**:如树状数组、线段树(poj2528, poj2828, poj2777, poj2886, poj2750)。 2. **平衡树**:如AVL树、红黑树等(poj2482, poj2352)。 3. **并查集**:用于处理不相交集合的问题(poj1195, poj...
+ poj2528, poj2828, poj2777, poj2886, poj2750 * 静态二叉检索树 + poj2482, poj2352 * 树状树组 + poj1195, poj3321 * RMQ + poj3264, poj3368 * 并查集的高级应用 + poj1703, poj2492 * KMP算法 + poj1961...
ACM大赛准备课程总结 本文总结了参加ACM大赛需要准备的课程,...4. poj2528、poj2828、poj2777、poj2886、poj2750 通过学习和掌握这些知识点,可以帮助你更好地准备ACM大赛,并提高自己的编程能力和解决问题的能力。
- 示例题目:poj2528, poj2828, poj2777, poj2886, poj2750 - **树状数组** - 示例题目:poj2482, poj2352 - **并查集** - 示例题目:poj1195, poj3321 - **区间查询(RMQ)** - 示例题目:poj3264, poj3368 ...
- 示例题目:POJ 2528, POJ 2828, POJ 2777, POJ 2886, POJ 2750 - **二分法**:在特定区间内进行搜索,适用于求解数值优化问题。 - 示例题目:POJ 2031, POJ 1039 ##### 5. 数学问题 - **组合数学**:涉及排列...
- **示例题目**: POJ 3267, POJ 1836, POJ 1260, POJ 2533, POJ 3176, POJ 1080, POJ 1159 - **注意事项**: 理解每种模型的状态定义和转移方程。 #### 六、数学 **1. 组合数学** - **定义**: 研究组合结构的...
1. **高级数据结构**(如poj2528, poj2828, poj2777, poj2886, poj2750):包括线段树、树状数组、Trie树等,用于解决复杂的数据查询和更新问题。 2. **平衡树**(如poj2482, poj2352):如AVL树、红黑树等,保持树...
- **ZOJ 1610** 和 **POJ 2777**:这两道题都是典型的线段覆盖问题,需要利用线段树来解决。基本思路是通过线段树维护每个区间是否被覆盖的状态。对于每个覆盖请求,更新线段树对应区间中的覆盖状态,并统计完全被...
2505 2521 2538 2546 2551 2590 2593 2601 2665 2680 2739 2752 2761 2762 2777 2800 2891 2893 2992 3030 3041 3132 3159 3187 3204 3270 3277 3281 3297 3321 3414 3436 3461 3650 3663 3664 3672 3740
【标题】: "POJ经典268题的源码,ACMer必备" 这是一份包含POJ(Problem Setter's Online Judge)网站上268个经典编程问题的源代码集合,是专为ACMer(参与ACM/ICPC国际大学生程序设计竞赛的选手)准备的宝贵资源。...
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1011 1012 1013 1014 ...2777 2780 2782 2812 2818 2840 2908 2922 2934 2965 2983 2993 2996 3020 3041 3168 3169 3176 3183 3184 3185 3191 3193 3214 3219 3224 ...
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1011 1012 1013 1014 ...2777 2812 2818 2840 3168 3219 3224 3250 3253 3278 3302 3311 3312 3325 3348 3349 3355 3357 3372 3386 3400 3421 3425 3427 3438 3452 ...