[SMOJ1833]小球染色
来源:互联网 发布:linux 线程同步 编辑:程序博客网 时间:2024/05/18 15:57
这题很明显,就是要实现两种操作:区间修改和单点查询,是典型的数据结构裸题,可以用线段树解决。
因为题目没有太多好讲的,我们不妨先回顾一下线段树这个数据结构,最后再稍来点拨一下本题。
首先还是要回到本质,数据结构到底是什么?为什么 OI 的学习越到后面,要花一百多甚至几百行去编写一个数据结构?
我们来看 wikipedia 对数据结构的定义,“In computer science, a data structure is a particular(特殊的) way of organizing data in a computer so that it can be used efficiently(有效地).”
由此可见,数据结构是一种强有力的辅助手段,帮助我们更好地处理我们所拥有的数据,或在运算时大幅度提高效率。
效率这个词,在 OI 竞赛中实在是太重要了。因此也就引发了 OI 选手对数据结构的追求,以至于早就有人提出“程序=算法+数据结构”的概念。
再回到线段树来看。线段树是处理区间问题时的利器,可以参考 04 年国家集训队有两篇论文对此作了较详细的阐述。无论是单点修改、区间查询,区间修改、单点查询……线段树都可以在
对一棵线段树的操作可以看成对一条线段的操作,其中每个结点对应管辖原线段中的一小段,每个结点要么没有儿子(叶子结点),要么有两个儿子。
当我们把一个区间修改之后,如果一层一层递归下去再修改儿子,显然是非常慢的,不能够符合我们对数据结构的需求,于是 lazy-tag 思想应运而生。
其精华就是:反正我只有在需要查询的时候才需要知道某一段最新的值,那么之前如果修改了某一段,就先“置之不理”,在需要进行递归的时候(无论是 update 还是 query 都好),顺便把标记打散往下带。这样一来效率就可以得到飞跃。
事实上,利用线段树解决问题,关键在于每个结点要记录什么值?
对于此题,其实就是一段区间是否为统一的颜色的问题。如果某段区间的颜色统一,那么就可以往下传。虽然可以另外加 bool 变量标记,但是把区间的颜色值赋为 0 也是一种可行的方法,毕竟题目中合法涂色是不可能出现 0 的。
时间复杂度:
参考代码:
#include <algorithm>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>using namespace std;const int maxn = 2e5 + 100;struct SegmentTree { //写成结构体的形式方便操作 struct Tnode { int l, r; int lch, rch; int val; Tnode () { lch = rch = val = 0; } } tree[maxn << 2]; int freePoint; SegmentTree () { freePoint = 0; } int getPoint(int l, int r) { //动态分配法,更灵活,避免造成浪费 int root = ++freePoint; tree[root].l = l; tree[root].r = r; return root; } int build(int l, int r) { int root = getPoint(l, r); if (l < r) { int mid = (l + r) >> 1; tree[root].lch = build(l, mid); tree[root].rch = build(mid + 1, r); } return root; } void pushDown(int root) { //打散 if (tree[root].val) { tree[tree[root].lch].val = tree[root].val; tree[tree[root].rch].val = tree[root].val; tree[root].val = 0; } } void update(int l, int r, int color, int root) { Tnode& node = tree[root]; if (node.r < l || r < node.l) return; if (l <= node.l && node.r <= r) { tree[root].val = color; return; } pushDown(root); update(l, r, color, node.lch); update(l, r, color, node.rch); } int queryOne(int pos, int root) { Tnode& node = tree[root]; if (node.l == pos && node.r == pos) return node.val; pushDown(root); if (pos <= tree[node.lch].r) return queryOne(pos, node.lch); else return queryOne(pos, node.rch); }} SegT;int n, m;int main(void) { freopen("1833.in", "r", stdin); freopen("1833.out", "w", stdout); scanf("%d%d", &n, &m); int root = SegT.build(1, n); for (int i = 0; i < m; i++) { int order; scanf("%d", &order); if (order == 1) { int a, b, c; scanf("%d%d%d", &a, &b, &c); SegT.update(a, b, c, root); } if (order == 2) { int x; scanf("%d", &x); printf("%d\n", SegT.queryOne(x, root)); } } return 0;}
- [SMOJ1833]小球染色
- 小球
- 小球
- 小球
- 小球
- 染色
- 染色
- 染色
- 称小球
- 找小球
- 小球下落
- 重力小球
- 小球落地
- 往返小球
- 小球滚动
- 小球下落
- 小球弹跳
- 重力小球
- session、cookie实现免登录
- Least Common Multiple
- 如何用 Visual studio 2003/2005 调试 ASP 应用程序、JavaScript 代码
- Linux数据管理——文件锁定
- jQuery动态设置样式(style、css)
- [SMOJ1833]小球染色
- this module
- 内存与swap
- Ext学习(三)Ext.util包下相关类
- 通过MCU实现Altera FPGA在线升级
- Android 监听手机GPS打开状态
- Android 5.1实现休眠的方法
- Visual Studio 2005调试ASP脚本程序的方法--
- TCP连接建立与关闭数据包捕获