网址https://vjudge.net/problem/POJ-3468
最近学了线段树,搞了一下区间更新。模板题吧。
写一下自己需要记住的点吧。
1.空间要为节点数的4倍,我在网上找了一下,大概意思是这样
建树后可能出现这种情况(图片来自http://scinart.github.io/acm/2014/03/19/acm-segment-tree-space-analysis/)
结果在最下面的一行原本没完全使用却占用了空间,占用的是比这个图刚刚大的完美二叉树空间。
计算一下此图空间:((n-1)*2-1+1)*2-1=4n-5
n-1倒数第二行空间。*2-1,,除去最后一行的总空间,,+1最后一行空间。
2.类型要为long long int 类型,因为最后会超int范围
3.被标记的点已经更新完信息。等待向下更新标记。
4.延迟标记。
思想:对于要更新的区段,将其记录在祖先节点,而不完全将祖先节点记录整个区间
的子孙节点信息更新。当需要使用其下的子孙节点时再向下更新信息。这种方式大大减少了
时间复杂度。
方式:修改与查询时,遇到节点,查看其是否被标记。是的话就向下传递标记,更新子节点信息,并消除父节点标记。
5.建立的图如下。。。(好丑)

6.具体地方在里面备注

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
/******************************************************/
#define LL long long int
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define L rt<<1
#define R rt<<1|1
#define N 100000+9
#define pow(a) a*a
#define INF 0x3f3f3f3f
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
/*********************************************************/
LL n, q;
LL dat[N<<2];
LL sum[N<<2];
LL addmark[N<<2];
void pushup(LL rt){sum[rt] = sum[L] + sum[R];
}
void pushdown(LL rt, LL len){if (addmark[rt]){addmark[L] += addmark[rt];addmark[R] += addmark[rt];sum[L] += addmark[rt]*(len - (len>>1));//这里要用rt,不用L。加更改后的值sum[R] += addmark[rt]*(len>>1);addmark[rt] = 0;}
}
void build(LL l, LL r, LL rt){addmark[rt] = 0;if (l == r){scanf("%lld", &sum[rt]);return;}LL m = (l + r) / 2;build(lson);build(rson);pushup(rt);
}
LL query(LL a,LL b,LL l, LL r, LL rt){if (a <= l&&r <= b){return sum[rt];}LL m = (l + r) / 2;LL res = 0;pushdown(rt, r - l + 1);if (a <= m)res+=query(a, b, lson);if (b>m)res+=query(a, b, rson);return res;
}void update(LL a, LL b, LL l, LL r, LL rt, LL c){if (a <= l&&r <= b){addmark[rt] += c;   sum[rt] += c * (r - l + 1);return;}pushdown(rt, r-l+1);    //向下传递标记,更新左右儿子信息LL m = (l + r) / 2;if(a<=m)update(a, b, lson, c);if(b>m)update(a, b, rson, c);pushup(rt);    //向上更新
}
int main(){while (~scanf("%lld%lld", &n, &q)){build(1, n, 1);while (q--){char s[2];scanf("%s", s);if (s[0] == 'Q'){LL a, b;scanf("%lld%lld", &a, &b);LL res = query(a, b, 1, n, 1);printf("%lld\n", res);}else{LL a, b, c;scanf("%lld%lld%lld", &a, &b, &c);update(a, b, 1, n, 1, c);}}}
}

HDU1689区间更新

更新的时候,从顶节点一路往下推。当遇到标记时,将标记向下传递。因为在某区间段更新是在递归最后实现的,所以之前的传递造成的标记会被更新的标记覆盖。更新结束之后,要实现求和的功能。

求和过程也是一路从上往下找。当遇到有标记的节点时,就返回标记的值*区间长度,即该区间的总和。当搜寻到叶子节点,即l==r时,如果有标记,返回标记,没有则返回1(初始值为1,不曾改变)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
/******************************************************/
#define LL long long int
#define mem(a,b) memset(a,b,sizeof(a))
#define m ((l+r)/2)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define L rt<<1
#define R rt<<1|1
#define N 100000+1
#define pow(a) a*a
#define INF 0x3f3f3f3f
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
/*********************************************************/
/*1
10
2
1 5 2
5 9 3*/
LL t, n, q;
LL addmark[N<<2];void pushdown(LL rt){if (addmark[rt]){addmark[L] = addmark[rt];addmark[R] = addmark[rt];addmark[rt] = 0;}
}
void update(LL a, LL b, LL c, LL l, LL r, LL rt){if (a<=l&&r<=b){addmark[rt] = c;return;}pushdown(rt);if (a <= m)update(a, b, c, lson);if (b > m)update(a, b, c, rson);
}LL add(LL l, LL r, LL rt){if (addmark[rt]){return addmark[rt] * (r - l + 1);}if (l == r){if (addmark[rt])return addmark[rt];elsereturn 1;}LL res = 0;res+=add(lson);res+=add(rson);return res;
}
int main(){cin >> t;LL cnt = 1;while (t--){mem(addmark, 0);scanf("%lld%lld", &n, &q);while (q--){LL a, b, c;scanf("%lld%lld%lld", &a, &b, &c);update(a, b, c, 1, n, 1);}printf("Case %lld: The total value of the hook is %lld.\n",cnt++, add(1, n, 1));}
}

区间更新POJ3468 HDU1698相关推荐

  1. poj3468 线段树区间更新+区间查询

    题目链接: http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS   Memory Limi ...

  2. java-HDU1698(线段树的区间更新,和区间查询)

    HDU1698: 题目意思: Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  3. HDU 5861 Road 线段树区间更新单点查询

    题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=5861 Road Time Limit: 12000/6000 MS (Java/Othe ...

  4. (转)线段树的区间更新

    原文地址:http://blog.csdn.net/zip_fan/article/details/46775633 写的很好,昨天刚刚开始写线段树,有些地方还不是很明白,看了这篇博文,学会了数组形式 ...

  5. hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询

    点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...

  6. HDU ACM 4031 Attack (树状数组--单点查询+区间更新)

    http://acm.hdu.edu.cn/showproblem.php?pid=4031 用了树状数组的区间更新 单点查找(一般为单点更新 区间查找) 例如 区间(2,4)加1 则Updata(2 ...

  7. hdu 5692 Snacks(dfs序+线段树区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5692 解题思路:这道题是树节点的点权更新,而且涉及到子树,常用的思路是利用dfs序,用线段树来对区间进 ...

  8. hdu 1698(线段树区间更新)

    解题思路:线段树区间更新水题. #include<iostream> #include<cstdio> #include<cstring> using namesp ...

  9. hdu 3577(线段树区间更新)

     题意:输入一个t,表示有t组测试数据: 接下来一行,输入两个数,k,m,其中k表示这个辆车最多可以坐这么多人,m表示有m次询问能否上车: 每一次询问,输入两个数a,b,表示该乘客能否在a站台上车 ...

最新文章

  1. 学术会议,已沦为表演...
  2. MySQL的共享锁和独占锁
  3. 计算机网络课程优秀备考PPT之第五章网络层(五)
  4. Android_注解+反射代替findViewById()
  5. bogofilter notes
  6. Redis高级特性及优化
  7. 玩转GIT系列之【git pull和git fetch的区别】
  8. 学习ASP.NET Core,怎能不了解请求处理管道[2]: 服务器在管道中的“龙头”地位
  9. 1分钟了解相似性推荐
  10. python中的__slots__
  11. sitemesh3.0的配置以及在静态html中的使用
  12. J2EE常用Listener(转载)
  13. 洛谷P1274-魔术数字游戏
  14. Visio图片导入到Word里面的步骤
  15. html实现验证码效果,html5使用canva实现验证码效果(代码实例)
  16. 在Kotlin中@Suppress可能取到的值
  17. 命令行模式下运行js文件
  18. Android打开WIFI、关闭WIFI、检测当前WIFI状态
  19. 有哪些小巧舒适的蓝牙耳机?推荐几款小巧且舒适的蓝牙耳机
  20. requests库和lxml库爬取彼岸图网的图片

热门文章

  1. 句子成分-主语/宾语/表语/同位语-4月1号
  2. python numba cuda_Numba:基于CUDA加速的高性能Python
  3. 用python生成万年历
  4. Unity Animator简单使用
  5. OPPOFindX5Pro和中兴Axon40Ultra哪个配置好 哪个更值得买
  6. u盘格式化中途强退,会不会损坏?
  7. SVN检出项目时中途停止
  8. 迅速建立自信的10种方法
  9. 为什么说php是c写的,Phper 学 C 兴趣入门 - 为什么 php 手册里经常说某个字符串函数是二进制安全的...
  10. Rust:Rust语言介绍