HDU 1698 Just a Hook(线段树+lazy)
2015-07-23 15:49
337 查看
题目链接:Click here
题意:给你n长度的钩子,每单位的初始值为1,然后m个操作,将(x,y)之间的值变为z,求最后n长度的值的和。
思路:使用lazy策略。引用一下概念:
“lazy-tag思想,记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。”
通俗的解释我理解的Lazy意思,比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,它的节点标记为f,这时tree[f].l == a && tree[f].r == b 这时我们可以一步更新此时rt节点的sum[rt]的值,sum[f] += c * (tree[f].r - tree[f].l + 1),注意关键的时刻来了,如果此时按照常规的线段树的update操作,这时候还应该更新rt子节点的sum[]值,而Lazy思想恰恰是暂时不更新f子节点的sum[]值,到此就return,直到下次需要用到f子节点的值的时候才去更新,这样避免许多可能无用的操作,从而节省时间 。
PS:这道题我参考了很多人的解法,感觉适应不了他们的代码风格,于是自己写了我认为比较容易理解的代码。可能会看起来比较繁琐
题意:给你n长度的钩子,每单位的初始值为1,然后m个操作,将(x,y)之间的值变为z,求最后n长度的值的和。
思路:使用lazy策略。引用一下概念:
“lazy-tag思想,记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。”
通俗的解释我理解的Lazy意思,比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,它的节点标记为f,这时tree[f].l == a && tree[f].r == b 这时我们可以一步更新此时rt节点的sum[rt]的值,sum[f] += c * (tree[f].r - tree[f].l + 1),注意关键的时刻来了,如果此时按照常规的线段树的update操作,这时候还应该更新rt子节点的sum[]值,而Lazy思想恰恰是暂时不更新f子节点的sum[]值,到此就return,直到下次需要用到f子节点的值的时候才去更新,这样避免许多可能无用的操作,从而节省时间 。
PS:这道题我参考了很多人的解法,感觉适应不了他们的代码风格,于是自己写了我认为比较容易理解的代码。可能会看起来比较繁琐
#include <iostream> #include <cstring> #include <cstdio> #include <queue> using namespace std; int m[500005]; int add[500005]; //lazy策略使用的标号 void build(int left, int right, int f) {//建立线段树 add[f] = 0; //初始时全部归零 int mid; mid = (left + right) / 2; m[f] = 1; if(left == right) return; build(left, mid, f * 2); build(mid + 1, right, f * 2 + 1); m[f] = m[f*2] + m[f*2+1]; } void update(int a, int b, int w,int left, int right, int f) {//更新 int mid; mid = (left + right) / 2; if(a <= left && b >= right) { add[f] = w; //这里直接将标号更新,线段树更新,直接返回,而不更新子节点 m[f] = w * (right - left + 1); return; } if(add[f]) { int kk; kk = right - left + 1; add[f*2] = add[f]; add[f*2+1] = add[f]; m[f*2] = (kk - kk / 2) * add[f]; m[f*2+1] = (kk / 2) * add[f]; add[f] = 0; } if(a <= mid) update(a, b, w, left, mid, f * 2); if(b > mid) update(a, b, w, mid + 1, right, f * 2 + 1); m[f] = m[f*2] + m[f*2+1]; } int main() { int n, T, s, x, y, w; scanf("%d",&T); for(int k = 1; k <= T; k++) { scanf("%d",&n); build(1, n, 1); scanf("%d",&s); while(s--) { scanf("%d%d%d", &x, &y, &w); update(x, y, w, 1, n, 1); } printf("Case %d: The total value of the hook is %d.\n", k, m[1]); } return 0; }
相关文章推荐
- 矩阵求逆
- 合并排序的递归实现
- iOS 自己封装的网络请求,json解析的类
- STM32启动文件2.02过程详解
- 再会鸟哥LINU
- 关于数据库迭代更新
- Word 中添加目录的一般方法
- iOS7+ 扫描二维码和条形码实现 耗时操作
- hdu3555 Bomb
- 一种简单有效的个性化推荐方法
- Java学习总结:反射机制
- JavaScript对象继承的方法
- CentOS的基础优化
- C#中ArrayList类的使用
- OOA/OOD/OOP
- 南阳oj NYOJ 数据结构 题目93 汉若塔(三)
- CVS错误:cvs commit: "..." should be removed and is still there (or is back again)
- md5 二进制数据
- 通过odp.net方式连接Oracle数据库
- 网络编程(网络基础,OSI参考模型,UDP传输协议,TCP传输协议,URL类和URLConnection类)